Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/src/man/man3/hm2_pktuart.3.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,15 @@ This is typically a multi-step process:
1. rxstatus indicates that there are packets of data, but at this point we need to know how big each packet is (and reading two much or two little data from the FIFOs will cause problems).
2. Queue a read of the frame sizes. **hm2_pktuart_queue_get_frame_sizes(name, fsizes[])**
On return, the fsizes[] array will have been loaded with the frame sizes (size in bytes).
The function returns the number of frame-size reads queued, or a negative error code.
If fsizes are [8] [7] [6] and you only read 1 frame from the data FIFO then on the next call to get_frame_sizes the returned array would be [7] [6].
3. Wait one thread cycle to get the data. Note that there is no serial latency here, the data is already on the FPGA but we can only know how much data to request once we know the packet size
4. Queue enough data reads to get all the data frames that the packet is spread over.
int hm2_pktuart_queue_read_data(name, data, bytes)
On return the data[] array will have been loaded with enough 32-bit frames to include "bytes" bytes.
The function returns the number of 32-bit data reads queued, or a negative error code.
Both queue helpers stop at the first queue failure; earlier reads may already
be queued. A successful return does not confirm completion of hardware I/O.
5. Parse the data.

=== Data Formats ===
Expand Down
107 changes: 57 additions & 50 deletions src/hal/drivers/mesa-hostmot2/pktuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ int hm2_pktuart_parse_md(hostmot2_t *hm2, int md_index)
// For the time being we assume that all PktUARTS come on pairs
if(inst->clock_freq == 0) {
inst->clock_freq = md->clock_freq;
r = rtapi_snprintf(inst->name, sizeof(inst->name), "%s.pktuart.%01d", hm2->llio->name, i);
rtapi_snprintf(inst->name, sizeof(inst->name), "%s.pktuart.%01d", hm2->llio->name, i);
HM2_PRINT("created PktUART Interface function %s.\n", inst->name);
}
if(md->gtag == HM2_GTAG_PKTUART_TX) {
Expand Down Expand Up @@ -300,24 +300,24 @@ static int config_tx(const char *name, const hostmot2_t* hm2, hm2_pktuart_instan
}

if((cfg->flags & HM2_PKTUART_CONFIG_FORCECONFIG) || bitrate != inst->tx_bitrate) {
inst->tx_bitrate = bitrate;
if((r = writefn(hm2->llio, inst->tx_bitrate_addr, &bitrate, sizeof(bitrate))) < 0) {
if((r = writefn(hm2->llio, inst->tx_bitrate_addr, &bitrate, sizeof(bitrate))) == 0) {
HM2_ERR("Configure TX baudrate: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
inst->tx_bitrate = bitrate;
}
if((cfg->flags & HM2_PKTUART_CONFIG_FORCECONFIG) || mode != inst->tx_mode) {
inst->tx_mode = mode;
if((r = writefn(hm2->llio, inst->tx_mode_addr, &mode, sizeof(mode))) < 0) {
if((r = writefn(hm2->llio, inst->tx_mode_addr, &mode, sizeof(mode))) == 0) {
HM2_ERR("Configure TX mode: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
inst->tx_mode = mode;
}
if(cfg->flags & HM2_PKTUART_CONFIG_FLUSH) {
rtapi_u32 buff = HM2_PKTUART_CLEAR; // clear data FIFO and count register
if((r = writefn(hm2->llio, inst->tx_mode_addr, &buff, sizeof(buff))) < 0) {
if((r = writefn(hm2->llio, inst->tx_mode_addr, &buff, sizeof(buff))) == 0) {
HM2_ERR("Configure TX flush: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
}
return 0;
Expand Down Expand Up @@ -380,24 +380,24 @@ static int config_rx(const char *name, const hostmot2_t *hm2, hm2_pktuart_instan
}

if((cfg->flags & HM2_PKTUART_CONFIG_FORCECONFIG) || bitrate != inst->rx_bitrate) {
inst->rx_bitrate = bitrate;
if((r = writefn(hm2->llio, inst->rx_bitrate_addr, &bitrate, sizeof(bitrate))) < 0) {
if((r = writefn(hm2->llio, inst->rx_bitrate_addr, &bitrate, sizeof(bitrate))) == 0) {
HM2_ERR("Configure RX baudrate: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
inst->rx_bitrate = bitrate;
}
if((cfg->flags & HM2_PKTUART_CONFIG_FORCECONFIG) || mode != inst->rx_mode) {
inst->rx_mode = mode;
if((r = writefn(hm2->llio, inst->rx_mode_addr, &mode, sizeof(mode))) < 0) {
if((r = writefn(hm2->llio, inst->rx_mode_addr, &mode, sizeof(mode))) == 0) {
HM2_ERR("Configure RX mode: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
inst->rx_mode = mode;
}
if(cfg->flags & HM2_PKTUART_CONFIG_FLUSH) {
rtapi_u32 buff = HM2_PKTUART_CLEAR; // clear data FIFO and count register
if((r = writefn(hm2->llio, inst->rx_mode_addr, &buff, sizeof(buff))) < 0) {
if((r = writefn(hm2->llio, inst->rx_mode_addr, &buff, sizeof(buff))) == 0) {
HM2_ERR("Configure RX flush: hm2->llio->%s failure %s (error %d)\n", writenm, name, r);
return r;
return -EIO;
}
}
return 0;
Expand Down Expand Up @@ -456,10 +456,10 @@ static void perform_reset(const char *name, int queue)
}

// clear sends, data FIFO and count register
if((i = wr(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) < 0)
if((i = wr(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) == 0)
HM2_ERR("Failed to %s reset of TX data and FIFO (error %d)\n", msg, i);
// clear receives, data FIFO and count register
if((i = wr(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) < 0)
if((i = wr(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) == 0)
HM2_ERR("Failed to %s reset of RX data and FIFO (error %d)\n", msg, i);
}

Expand Down Expand Up @@ -515,55 +515,55 @@ int hm2_pktuart_setup(const char *name, unsigned bitrate, rtapi_s32 tx_mode, rta
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); // 20 bits in v0 & v1
}
if(buff != inst->tx_bitrate) {
inst->tx_bitrate = buff;
if((r = hm2->llio->write(hm2->llio, inst->tx_bitrate_addr, &buff, sizeof(rtapi_u32))) < 0) {
if((r = hm2->llio->write(hm2->llio, inst->tx_bitrate_addr, &buff, sizeof(rtapi_u32))) == 0) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on tx bitrate (error %d)\n", name, r);
return r;
return -EIO;
}
inst->tx_bitrate = buff;
}
if(hm2->pktuart.rx_version >= 2) {
buff = (rtapi_u32)((bitrate * 16777216.0)/inst->clock_freq); // 24 bits in v2+
} else {
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); // 20 bits in v0 & v1
}
if(buff != inst->rx_bitrate) {
inst->rx_bitrate = buff;
if((r = hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff, sizeof(rtapi_u32))) < 0) {
if((r = hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff, sizeof(rtapi_u32))) == 0) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on rx bitrate (error %d)\n", name, r);
return r;
return -EIO;
}
inst->rx_bitrate = buff;
}
}

if(tx_mode >= 0) {
buff = ((rtapi_u32)tx_mode) & HM2_PKTUART_TXMODE_MASK;
if((r = hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) < 0) {
if((r = hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) == 0) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on tx_mode (error %d)\n", name, r);
return r;
return -EIO;
}
}

if(rx_mode >= 0) {
buff = ((rtapi_u32)rx_mode) & HM2_PKTUART_RXMODE_MASK;
if((r = hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) < 0) {
if((r = hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) == 0) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on rx_mode (error %d)\n", name, r);
return r;
return -EIO;
}
}

buff = HM2_PKTUART_CLEAR;
if(txclear == 1) {
// clear sends, data FIFO and count register
if((r = hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) < 0) {
if((r = hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32))) == 0) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on tx clear (error %d)\n", name, r);
return r;
return -EIO;
}
}
if(rxclear == 1) {
// clear receives, data FIFO and count register
if((r = hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) < 0 ) {
if((r = hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32))) == 0 ) {
HM2_ERR("PktUART setup: hm2->llio->write failure %s on rx clear (error %d)\n", name, r);
return r;
return -EIO;
}
}

Expand Down Expand Up @@ -615,9 +615,9 @@ int hm2_pktuart_send(const char *name, const unsigned char data[], rtapi_u8 *num
while(c < count - 3) {
rtapi_u32 buff = data[c] + (data[c+1] << 8) + (data[c+2] << 16) + (data[c+3] << 24);
r = hm2->llio->queue_write(hm2->llio, hm2->pktuart.instance[inst].tx_addr, &buff, sizeof(buff));
if(r < 0) {
if(r == 0) {
HM2_ERR("%s send: hm2->llio->queue_write failure\n", name);
return r;
return -EIO;
}
c += 4;
}
Expand All @@ -634,9 +634,9 @@ int hm2_pktuart_send(const char *name, const unsigned char data[], rtapi_u8 *num
return -1;
} // end switch
r = hm2->llio->queue_write(hm2->llio, hm2->pktuart.instance[inst].tx_addr, &buff, sizeof(buff));
if(r < 0) {
if(r == 0) {
HM2_ERR("%s send: hm2->llio->queue_write failure\n", name);
return r;
return -EIO;
}
}
(*num_frames)++;
Expand All @@ -652,9 +652,9 @@ int hm2_pktuart_send(const char *name, const unsigned char data[], rtapi_u8 *num
// Not possible to check for errors on the fly when using queued
// transfers. The data does not arrive immediately. Therefore, no
// checks can be done here.
if(r < 0) {
if(r == 0) {
HM2_ERR("%s send: hm2->llio->queue_write failure\n", name);
return r;
return -EIO;
}
}
return count;
Expand Down Expand Up @@ -698,9 +698,9 @@ int hm2_pktuart_read(const char *name, unsigned char data[], rtapi_u8 *num_frame
// First poll the mode register for a non zero frames received count
// (mode register bits 20..16)
r = hm2->llio->read(hm2->llio, hm2->pktuart.instance[inst].rx_mode_addr, &buff, sizeof(rtapi_u32));
if(r < 0) {
if(r == 0) {
HM2_ERR("%s read: hm2->llio->read failure\n", name);
return r;
return -EIO;
}
if(buff & (0x1 << 21)) {
countp = (buff >> 16) & 0x1f;
Expand Down Expand Up @@ -753,6 +753,10 @@ int hm2_pktuart_read(const char *name, unsigned char data[], rtapi_u8 *num_frame
of received packets. Since it is a FIFO it must only be read once after it
has be determined that there are packets available to read. */
r = hm2->llio->read(hm2->llio, hm2->pktuart.instance[inst].rx_fifo_count_addr, &buff, sizeof(buff));
if(r == 0) {
HM2_ERR("%s read: hm2->llio->read failure\n", name);
return -EIO;
}

countb = buff & 0x3ff; // PktUARTr receive count register Bits 9..0 : bytes in receive packet

Expand Down Expand Up @@ -791,9 +795,9 @@ int hm2_pktuart_read(const char *name, unsigned char data[], rtapi_u8 *num_frame
while(c < countb - 3) {
r = hm2->llio->read(hm2->llio, hm2->pktuart.instance[inst].rx_addr, &buff, sizeof(buff));

if(r < 0) {
if(r == 0) {
HM2_ERR("%s read: hm2->llio->read failure\n", name);
return r;
return -EIO;
}

data[bytes_total+c+0] = (buff & 0x000000FF); // i*frame_sizes[i]
Expand All @@ -805,9 +809,9 @@ int hm2_pktuart_read(const char *name, unsigned char data[], rtapi_u8 *num_frame

if(countb - c) {
r = hm2->llio->read(hm2->llio, hm2->pktuart.instance[inst].rx_addr, &buff, sizeof(buff));
if(r < 0) {
HM2_ERR("%s read: hm2->llio->queue_write failure\n", name);
return -1;
if(r == 0) {
HM2_ERR("%s read: hm2->llio->read failure\n", name);
return -EIO;
}
switch(countb - c) {
case 1:
Expand Down Expand Up @@ -867,11 +871,12 @@ int hm2_pktuart_queue_get_frame_sizes(const char *name, rtapi_u32 fsizes[])
for(j = 0; j < nfs; j++ ) {
r = hm2->llio->queue_read(hm2->llio, hm2->pktuart.instance[inst].rx_fifo_count_addr,
&fsizes[j], sizeof(rtapi_u32));
if(r < 0) {
if(r == 0) {
HM2_ERR("Unable to queue Rx FIFO count read %d of %d (error %d))\n", j, nfs, r);
return -EIO;
}
}
return j - 1;
return j;
}
EXPORT_SYMBOL_GPL(hm2_pktuart_queue_get_frame_sizes);

Expand Down Expand Up @@ -904,18 +909,20 @@ int hm2_pktuart_queue_read_data(const char *name, rtapi_u32 data[], int bytes)
HM2_ERR("%s has not been configured.\n", name);
return -EINVAL;
}
if(bytes < 0) return -EINVAL;

// queue enough reads to get the whole frame. Data will be transferred
// to data[] next thread cycle, direct from FPGA, no serial latency
int nrx = (bytes + 3) / 4; // Always full 32-bit words
for(i = 0; i < nrx; i++ ) {
r = hm2->llio->queue_read(hm2->llio, hm2->pktuart.instance[inst].rx_addr,
&data[i], sizeof(rtapi_u32));
if(r < 0) {
if(r == 0) {
HM2_ERR("Unable to queue Rx FIFO read %d of %d (error %d)\n", i, nrx, r);
return -EIO;
}
}
return i - 1;
return i;
}
EXPORT_SYMBOL_GPL(hm2_pktuart_queue_read_data);

Expand Down
Loading