Skip to content

Commit

Permalink
imxrt-multi: change RTT initialization
Browse files Browse the repository at this point in the history
Remove hard-coded RTT address and get it from memory map.
Change RTT initialization to keep existing buffer contents if buffers
are valid.
Allow more channels in the control block than defined at compile
time (they will not be usable by the userspace driver).

JIRA: RTOS-754
  • Loading branch information
jmaksymowicz committed Sep 27, 2024
1 parent df8b27b commit a2bd786
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 59 deletions.
102 changes: 73 additions & 29 deletions librtt/librtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ struct rtt_desc {
char tag[16];
unsigned int txChannels;
unsigned int rxChannels;
struct rtt_pipe channel[LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS];
struct rtt_pipe channel[];
};


Expand Down Expand Up @@ -113,7 +113,7 @@ static void performCacheOp(librtt_cacheOp_t op, volatile unsigned char *buf, uns

int librtt_checkTx(unsigned int ch)
{
if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->txChannels)) {
if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->txChannels) || (ch >= LIBRTT_TXCHANNELS)) {
return -ENODEV;
}

Expand All @@ -123,7 +123,7 @@ int librtt_checkTx(unsigned int ch)

int librtt_checkRx(unsigned int ch)
{
if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->rxChannels)) {
if ((librtt_common.rtt == NULL) || (ch >= librtt_common.rtt->rxChannels) || (ch >= LIBRTT_RXCHANNELS)) {
return -ENODEV;
}

Expand Down Expand Up @@ -290,37 +290,87 @@ int librtt_txCheckReaderAttached(unsigned int ch)
}


int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn)
static int librtt_verifyChannel(volatile struct rtt_desc *rtt, unsigned int ch, unsigned char *buffers, size_t buffersSize)
{
if ((LIBRTT_DESC_SIZE < sizeof(struct rtt_desc)) || (librtt_common.rtt != NULL)) {
unsigned char *bufEnd = buffers + buffersSize;
size_t sz = rtt->channel[ch].sz;
/* Check buffer size is non-zero and power of 2 */
if ((sz == 0) || ((sz & (sz - 1)) != 0)) {
return -EINVAL;
}

librtt_common.invalFn = invalFn;
librtt_common.cleanFn = cleanFn;
if ((rtt->channel[ch].ptr < buffers) || (rtt->channel[ch].ptr >= bufEnd)) {
return -EINVAL;
}

if (((rtt->channel[ch].ptr + rtt->channel[ch].sz) <= buffers) || ((rtt->channel[ch].ptr + rtt->channel[ch].sz) > bufEnd)) {
return -EINVAL;
}

return 0;
}

volatile struct rtt_desc *rtt = addr;

int n;
int librtt_verify(void *addr, size_t cbSize, void *buffers, size_t buffersSize, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn)
{
int n, ret;
if (cbSize < sizeof(struct rtt_desc)) {
return -EINVAL;
}

volatile struct rtt_desc *rtt = addr;
for (n = 0; n < librtt_tagLength; n++) {
if (librtt_tagReversed[n] != rtt->tag[librtt_tagLength - 1 - n]) {
break;
}
}

if (n == librtt_tagLength) {
if ((rtt->txChannels + rtt->rxChannels) <= (LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS)) {
librtt_common.rtt = rtt;
return 0;
if (n != librtt_tagLength) {
return -EINVAL;
}

size_t realCbSize = sizeof(struct rtt_desc) + ((rtt->txChannels + rtt->rxChannels) * sizeof(struct rtt_pipe));
if (cbSize < realCbSize) {
return -EINVAL;
}

int totalChannels = rtt->txChannels + rtt->rxChannels;
for (n = 0; n < totalChannels; n++) {
ret = librtt_verifyChannel(rtt, n, buffers, buffersSize);
if (ret != 0) {
return ret;
}

if (n < LIBRTT_TXCHANNELS) {
librtt_common.lastRd[n] = rtt->channel[n].rd;
}
}

memset((void *)rtt, 0, sizeof(*rtt));
librtt_common.invalFn = invalFn;
librtt_common.cleanFn = cleanFn;
librtt_common.rtt = rtt;
return 0;
}


int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn)
{
const size_t cbSize = sizeof(struct rtt_desc) + (LIBRTT_TXCHANNELS + LIBRTT_RXCHANNELS) * sizeof(struct rtt_pipe);
if ((LIBRTT_DESC_SIZE < cbSize) || (librtt_common.rtt != NULL)) {
return -EINVAL;
}

librtt_common.invalFn = invalFn;
librtt_common.cleanFn = cleanFn;

volatile struct rtt_desc *rtt = addr;

memset((void *)rtt, 0, cbSize);

rtt->txChannels = LIBRTT_TXCHANNELS;
rtt->rxChannels = LIBRTT_RXCHANNELS;

for (n = 0; n < librtt_tagLength; n++) {
for (int n = 0; n < librtt_tagLength; n++) {
rtt->tag[librtt_tagLength - 1 - n] = librtt_tagReversed[n];
}

Expand All @@ -336,32 +386,26 @@ int librtt_initChannel(int isTx, unsigned int ch, unsigned char *buf, size_t sz)
return -EINVAL;
}

unsigned int chMax = (isTx != 0) ? rtt->txChannels : rtt->rxChannels;
if ((ch >= chMax)) {
return -EINVAL;
}

/* Check buffer size is non-zero and power of 2 */
if ((sz == 0) || ((sz & (sz - 1)) != 0)) {
return -EINVAL;
}

const char *name = NULL;
if (isTx != 0) {
if (ch < LIBRTT_TXCHANNELS) {
name = librtt_txName[ch];
if ((ch >= LIBRTT_TXCHANNELS) || (ch >= rtt->txChannels)) {
return -EINVAL;
}
}
else {
if (ch < LIBRTT_RXCHANNELS) {
name = librtt_rxName[ch];
}
}

if (isTx != 0) {
name = librtt_txName[ch];
librtt_common.lastRd[ch] = 0;
}
else {
if ((ch >= LIBRTT_RXCHANNELS) || (ch >= rtt->rxChannels)) {
return -EINVAL;
}

name = librtt_rxName[ch];
ch += rtt->txChannels;
}

Expand Down
6 changes: 5 additions & 1 deletion librtt/librtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
typedef int (*librtt_cacheOp_t)(void *addr, unsigned int sz);


/* Initialize rtt descriptor if it is not initialized already */
/* Verify contents of rtt descriptor and initialize data structure if successful */
int librtt_verify(void *addr, size_t cbSize, void *buffers, size_t buffersSize, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn);


/* Initialize rtt descriptor */
int librtt_init(void *addr, librtt_cacheOp_t invalFn, librtt_cacheOp_t cleanFn);


Expand Down
101 changes: 72 additions & 29 deletions multi/imxrt-multi/rtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@
#include "rtt.h"


#ifndef RTT_ADDR
/* RTT descriptors location, last 256 bytes of DTCM */
#define RTT_ADDR (0x20040000 - 0x100)
#ifndef RTT_SYSPAGE_MAP_NAME
#define RTT_SYSPAGE_MAP_NAME "rtt"
#endif

#define RTT_TX_BUF_SIZE 1024
Expand Down Expand Up @@ -147,8 +146,11 @@ static int rtt_initOne(rtt_t *uart, int chn, unsigned char *buf)
uart->chn = chn;

int ret = 0;
ret = (ret == 0) ? librtt_initChannel(1, chn, buf, RTT_TX_BUF_SIZE) : ret;
ret = (ret == 0) ? librtt_initChannel(0, chn, buf + RTT_TX_BUF_SIZE, RTT_RX_BUF_SIZE) : ret;
if (buf != NULL) {
ret = (ret == 0) ? librtt_initChannel(1, chn, buf, RTT_TX_BUF_SIZE) : ret;
ret = (ret == 0) ? librtt_initChannel(0, chn, buf + RTT_TX_BUF_SIZE, RTT_RX_BUF_SIZE) : ret;
}

ret = (ret == 0) ? mutexCreate(&uart->lock) : ret;
/* TODO: calculate approx. baud rate based on buffer size and polling rate */
ret = (ret == 0) ? libtty_init(&uart->tty_common, &callbacks, TTY_BUF_SIZE, libtty_int_to_baudrate(115200)) : ret;
Expand All @@ -157,49 +159,90 @@ static int rtt_initOne(rtt_t *uart, int chn, unsigned char *buf)
}


int rtt_init(void)
static int rtt_getMemInfo(void **rttMemPtr_out, size_t *rttMemSz_out)
{
if (RTT_ACTIVE_CNT == 0) {
return EOK;
void *rttMemPtr = NULL;
size_t rttMemSz = 0;
meminfo_t mi;
mi.page.mapsz = -1;
mi.entry.kmapsz = -1;
mi.entry.mapsz = -1;
mi.maps.mapsz = 0;
mi.maps.map = NULL;
meminfo(&mi);

mi.maps.map = malloc(mi.maps.mapsz * sizeof(mapinfo_t));
if (mi.maps.map == NULL) {
return -ENOMEM;
}

/* Reserve memory for the descriptor and buffers */
intptr_t startAddr = (RTT_ADDR - (RTT_ACTIVE_CNT * (RTT_TX_BUF_SIZE + RTT_RX_BUF_SIZE))) & ~(_PAGE_SIZE - 1);
size_t mapSize = RTT_ADDR + LIBRTT_DESC_SIZE - startAddr;
unsigned char *rttBuffer = mmap(
NULL,
mapSize,
PROT_WRITE | PROT_READ,
MAP_ANONYMOUS | MAP_UNCACHED | MAP_PHYSMEM,
-1,
startAddr);
meminfo(&mi);
for (int i = 0; i < mi.maps.mapsz; i++) {
if (strcmp(mi.maps.map[i].name, RTT_SYSPAGE_MAP_NAME) == 0) {
rttMemPtr = (void *)mi.maps.map[i].vstart;
rttMemSz = mi.maps.map[i].vend - mi.maps.map[i].vstart;
break;
}
}

if (rttBuffer == MAP_FAILED) {
return -ENOMEM;
free(mi.maps.map);
if (rttMemPtr == NULL) {
return -ENODEV;
}

int ret = librtt_init((void *)RTT_ADDR, NULL, NULL);
*rttMemPtr_out = rttMemPtr;
*rttMemSz_out = rttMemSz;
return EOK;
}


int rtt_init(void)
{
int doInit = 0;
void *rttMemPtr = NULL;
size_t rttMemSz = 0;
int ret = rtt_getMemInfo(&rttMemPtr, &rttMemSz);
if (ret != 0) {
librtt_done();
munmap(rttBuffer, mapSize);
return ret;
}

unsigned char *buf = rttBuffer;
for (int i = 0, chn = 0; chn < RTT_CHANNEL_CNT; ++chn) {
size_t bufSz = rttMemSz - LIBRTT_DESC_SIZE;
void *cbAddr = rttMemPtr + bufSz;
ret = librtt_verify(
cbAddr,
LIBRTT_DESC_SIZE,
rttMemPtr,
bufSz,
NULL,
NULL);
if (ret != 0) {
doInit = 1;
ret = librtt_init(cbAddr, NULL, NULL);
if (ret != 0) {
return ret;
}
}

unsigned char *buf = (doInit != 0) ? rttMemPtr : NULL;
unsigned char *nextBuf = buf;
for (int i = 0, chn = 0; chn < RTT_CHANNEL_CNT; chn++, buf = nextBuf) {
if (rttConfig[chn] == 0) {
continue;
}

rtt_t *uart = &rtt_common.uarts[i++];
int ret = rtt_initOne(uart, chn, buf);
if (buf != NULL) {
nextBuf = buf + RTT_TX_BUF_SIZE + RTT_RX_BUF_SIZE;
if ((nextBuf - (unsigned char *)rttMemPtr) > bufSz) {
break;
}
}

ret = rtt_initOne(uart, chn, buf);
if (ret != 0) {
librtt_done();
munmap(rttBuffer, mapSize);
return ret;
}

buf += RTT_RX_BUF_SIZE + RTT_TX_BUF_SIZE;
}

beginthread(rtt_thread, IMXRT_MULTI_PRIO, rtt_common.stack, sizeof(rtt_common.stack), NULL);
Expand Down

0 comments on commit a2bd786

Please sign in to comment.