-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
devices: implement RTT pipe driver for debug probe
Implements driver for Real Time Transfer (RTT) which is a pipe interface based on basic memory reads and writes to transfer data bidirectionally between target and host. It uses debug probe JTAG or SWD (openocd, segger). Every target that supports so called "background memory access", which means that the target memory can be accessed by the debugger while the target is running, can be used. It is faster than semi hosting. JIRA: RTOS-531 NIL-462
- Loading branch information
Showing
29 changed files
with
604 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# | ||
# Makefile for pipe-rtt | ||
# | ||
# Copyright 2023-2024 Phoenix Systems | ||
# | ||
# %LICENSE% | ||
# | ||
|
||
OBJS += $(addprefix $(PREFIX_O)devices/pipe-rtt/, rtt.o device.o) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* Operating system loader | ||
* | ||
* RTT pipes: communication through debug probe (device) | ||
* | ||
* Copyright 2023-2024 Phoenix Systems | ||
* Author: Gerard Swiderski | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
#include <devices/devs.h> | ||
#include <hal/hal.h> | ||
#include <lib/lib.h> | ||
|
||
#include "rtt.h" | ||
|
||
static ssize_t pipe_read(unsigned int minor, addr_t offs, void *buff, size_t len, time_t timeout) | ||
{ | ||
(void)offs; | ||
(void)timeout; | ||
|
||
return rtt_read(minor + 1, buff, len); | ||
} | ||
|
||
|
||
static ssize_t pipe_write(unsigned int minor, addr_t offs, const void *buff, size_t len) | ||
{ | ||
(void)offs; | ||
|
||
return rtt_write(minor + 1, buff, len); | ||
} | ||
|
||
|
||
static int pipe_done(unsigned int minor) | ||
{ | ||
return rtt_check(minor + 1); | ||
} | ||
|
||
|
||
static int pipe_sync(unsigned int minor) | ||
{ | ||
return rtt_check(minor + 1); | ||
} | ||
|
||
|
||
static int pipe_map(unsigned int minor, addr_t addr, size_t sz, int mode, addr_t memaddr, size_t memsz, int memmode, addr_t *a) | ||
{ | ||
(void)addr; | ||
(void)sz; | ||
(void)memaddr; | ||
(void)memsz; | ||
(void)a; | ||
|
||
if (rtt_check(minor + 1) < 0) { | ||
return -ENODEV; | ||
} | ||
|
||
/* mode cannot be higher than map mode to copy data */ | ||
if ((mode & memmode) != mode) { | ||
return -EINVAL; | ||
} | ||
|
||
/* is not mappable to any region */ | ||
return dev_isNotMappable; | ||
} | ||
|
||
|
||
static int pipe_init(unsigned int minor) | ||
{ | ||
int res = rtt_check(minor + 1); | ||
if (res == 0) { | ||
lib_printf("\ndev/pipe: Initialized rtt channel(%d.%d)", DEV_PIPE, minor); | ||
} | ||
|
||
return res; | ||
} | ||
|
||
|
||
__attribute__((constructor)) static void pipe_reg(void) | ||
{ | ||
static const dev_handler_t h = { | ||
.init = pipe_init, | ||
.done = pipe_done, | ||
.read = pipe_read, | ||
.write = pipe_write, | ||
.erase = NULL, | ||
.sync = pipe_sync, | ||
.map = pipe_map, | ||
}; | ||
|
||
devs_register(DEV_PIPE, 1, &h); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* Operating system loader | ||
* | ||
* RTT pipes: communication through debug probe (driver) | ||
* | ||
* Copyright 2023-2024 Phoenix Systems | ||
* Author: Gerard Swiderski | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
#include <hal/hal.h> | ||
#include <lib/lib.h> | ||
|
||
|
||
#define RTT_TXCHANNELS 2 | ||
#define RTT_RXCHANNELS 2 | ||
|
||
/* | ||
* Note: RTT_TAG needs to be backward written string. This tag is used by | ||
* the RTT remote side e.g. openocd to find descriptor location during memory | ||
* scan, so as not to mislead the descriptor scan procedure, this tag needs | ||
* to be simply hidden before it is copied into RAM together with initialized | ||
* descriptors, that's why it is written backwards. | ||
* - Default RTT_TAG_REVERSED="EPIP TTR", which corresponds to "RTT PIPE" | ||
*/ | ||
|
||
#ifndef RTT_TAG_BACKWARD | ||
#define RTT_TAG_BACKWARD "EPIP TTR" | ||
#endif | ||
|
||
|
||
struct rtt_pipe { | ||
const char *name; | ||
unsigned char *ptr; | ||
unsigned int sz; | ||
volatile unsigned int wr; | ||
volatile unsigned int rd; | ||
unsigned int flags; | ||
}; | ||
|
||
|
||
struct rtt_desc { | ||
char tag[16]; | ||
unsigned int txChannels; | ||
unsigned int rxChannels; | ||
struct rtt_pipe txChannel[RTT_TXCHANNELS]; | ||
struct rtt_pipe rxChannel[RTT_RXCHANNELS]; | ||
}; | ||
|
||
|
||
static struct { | ||
/* NOTE: each buffer must be aligned to cache line */ | ||
unsigned char bytes[1024] __attribute__((aligned(32))); | ||
} rttBufferPool[RTT_TXCHANNELS + RTT_RXCHANNELS]; | ||
|
||
|
||
static const char rtt_tagBackward[] = RTT_TAG_BACKWARD; | ||
static const char *const rtt_txName[RTT_TXCHANNELS] = { "Console TX", "phoenixd TX" }; | ||
static const char *const rtt_rxName[RTT_RXCHANNELS] = { "Console RX", "phoenixd RX" }; | ||
static volatile struct rtt_desc *rtt = NULL; | ||
|
||
|
||
int rtt_check(int chan) | ||
{ | ||
if ((rtt == NULL) || (chan < 0) || (chan >= RTT_TXCHANNELS)) { | ||
return -ENODEV; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
|
||
ssize_t rtt_read(int chan, void *buf, size_t count) | ||
{ | ||
if (rtt_check(chan) < 0) { | ||
return -ENODEV; | ||
} | ||
|
||
hal_cpuDataMemoryBarrier(); | ||
|
||
unsigned char *srcBuf = (unsigned char *)rtt->rxChannel[chan].ptr; | ||
unsigned char *dstBuf = (unsigned char *)buf; | ||
unsigned int rd = rtt->rxChannel[chan].rd; | ||
unsigned int wr = rtt->rxChannel[chan].wr; | ||
unsigned int sz = rtt->rxChannel[chan].sz; | ||
size_t todo = count; | ||
|
||
while ((todo != 0) && (rd != wr)) { | ||
*dstBuf++ = srcBuf[rd]; | ||
rd = (rd + 1) % sz; | ||
todo--; | ||
} | ||
|
||
rtt->rxChannel[chan].rd = rd; | ||
|
||
hal_cpuDataMemoryBarrier(); | ||
|
||
return count - todo; | ||
} | ||
|
||
|
||
ssize_t rtt_write(int chan, const void *buf, size_t count) | ||
{ | ||
if (rtt_check(chan) < 0) { | ||
return -ENODEV; | ||
} | ||
|
||
hal_cpuDataMemoryBarrier(); | ||
|
||
const unsigned char *srcBuf = (const unsigned char *)buf; | ||
unsigned char *dstBuf = (unsigned char *)rtt->txChannel[chan].ptr; | ||
unsigned int sz = rtt->txChannel[chan].sz; | ||
unsigned int rd = (rtt->txChannel[chan].rd + sz - 1) % sz; | ||
unsigned int wr = rtt->txChannel[chan].wr; | ||
size_t todo = count; | ||
|
||
while ((todo != 0) && (rd != wr)) { | ||
dstBuf[wr] = *srcBuf++; | ||
wr = (wr + 1) % sz; | ||
todo--; | ||
} | ||
|
||
rtt->txChannel[chan].wr = wr; | ||
|
||
hal_cpuDataMemoryBarrier(); | ||
|
||
return count - todo; | ||
} | ||
|
||
|
||
static ssize_t rtt_writeBlocking(int chan, const void *buf, size_t count) | ||
{ | ||
const unsigned char *ptr = buf; | ||
size_t todo = count; | ||
time_t start = hal_timerGet(); | ||
|
||
while (todo > 0) { | ||
if ((hal_timerGet() - start) >= 100) { | ||
rtt->txChannel[chan].wr = rtt->txChannel[chan].rd; | ||
return -ETIME; | ||
} | ||
|
||
ssize_t len = rtt_write(chan, ptr, todo); | ||
if (len < 0) { | ||
return len; | ||
} | ||
todo -= len; | ||
ptr += len; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
|
||
void rtt_init(void *addr) | ||
{ | ||
unsigned int n, m; | ||
|
||
if (rtt != NULL) { | ||
return; | ||
} | ||
|
||
rtt = (volatile struct rtt_desc *)addr; | ||
hal_memset((void *)rtt, 0, sizeof(*rtt)); | ||
|
||
rtt->txChannels = RTT_TXCHANNELS; | ||
rtt->rxChannels = RTT_RXCHANNELS; | ||
|
||
m = 0; | ||
for (n = 0; n < rtt->txChannels; n++) { | ||
rtt->txChannel[n].name = rtt_txName[n]; | ||
rtt->txChannel[n].ptr = rttBufferPool[m].bytes; | ||
rtt->txChannel[n].sz = sizeof(rttBufferPool[m].bytes); | ||
m++; | ||
} | ||
|
||
for (n = 0; n < rtt->rxChannels; n++) { | ||
rtt->rxChannel[n].name = rtt_rxName[n]; | ||
rtt->rxChannel[n].ptr = rttBufferPool[m].bytes; | ||
rtt->rxChannel[n].sz = sizeof(rttBufferPool[m].bytes); | ||
m++; | ||
} | ||
|
||
n = 0; | ||
m = sizeof(rtt_tagBackward) - 1; | ||
while (n < sizeof(rtt->tag) && m > 0) { | ||
rtt->tag[n++] = rtt_tagBackward[--m]; | ||
} | ||
|
||
hal_consoleSetHooks(rtt_write); | ||
lib_consoleSetHooks(rtt_read, rtt_writeBlocking); | ||
} | ||
|
||
|
||
void rtt_done(void) | ||
{ | ||
if (rtt != NULL) { | ||
lib_consoleSetHooks(NULL, NULL); | ||
hal_memset((void *)rtt, 0, sizeof(*rtt)); | ||
rtt = NULL; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* Phoenix-RTOS | ||
* | ||
* Operating system loader | ||
* | ||
* RTT pipes: communication through debug probe (driver) | ||
* | ||
* Copyright 2023-2024 Phoenix Systems | ||
* Author: Gerard Swiderski | ||
* | ||
* This file is part of Phoenix-RTOS. | ||
* | ||
* %LICENSE% | ||
*/ | ||
|
||
#ifndef _RTT_H_ | ||
#define _RTT_H_ | ||
|
||
|
||
int rtt_check(int chan); | ||
|
||
|
||
ssize_t rtt_read(int chan, void *buf, size_t count); | ||
|
||
|
||
ssize_t rtt_write(int chan, const void *buf, size_t count); | ||
|
||
|
||
#endif /* end of _RTT_H_ */ |
Oops, something went wrong.