Skip to content

Commit

Permalink
piolib: Increase data_bytes range to 32-bits
Browse files Browse the repository at this point in the history
In many places, the number of bytes in a data transfer is stored as a
32-bit (or greater) value, but the ioctl API to the kernel stores it in
a 16-bit field, alongside which is a 16-bit gap due to the alignment
requirements of the pointer that follows.

Increase the size of data_bytes to a uint32_t, so that it can handle
larger transfers. Since using different sizes as either end can lead
to unpredictable results, a separate IOCTL is used for larger
transfers, allowing the kernel support to be determined and
backwards compatibility to be maintained.

See: raspberrypi#107

Signed-off-by: Phil Elwell <[email protected]>
  • Loading branch information
pelwell committed Dec 17, 2024
1 parent 9d884c7 commit 3da6b43
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
20 changes: 19 additions & 1 deletion piolib/examples/apitest.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ int main(int argc, const char **argv) {
pio_panic("RX FIFO is not empty");

offset = pio_add_program(pio, &genseq_program);
pio_sm_config_xfer(pio, sm, PIO_DIR_FROM_SM, 256, 1);
pio_sm_config_xfer(pio, sm, PIO_DIR_FROM_SM, 4096, 2);

pio_gpio_init(pio, gpio);
pio_sm_set_consecutive_pindirs(pio, sm, gpio, 1, true);
Expand Down Expand Up @@ -219,6 +219,24 @@ int main(int argc, const char **argv) {
sleep_ms(10);
}

if (!ret)
{
const uint32_t words = 0x10000;
uint32_t *bigbuf = malloc(words * sizeof(bigbuf[0]));

pio_sm_put_blocking(pio, sm, words - 1);
ret = pio_sm_xfer_data(pio, sm, PIO_DIR_FROM_SM, words * sizeof(bigbuf[0]), bigbuf);
if (!ret) {
for (i = words - 1; i >= 0; i--)
{
int v = bigbuf[words - 1 - i];
if (v != i)
printf(" %x: %x\n", i, v);
}
}
free(bigbuf);
}

if (ret)
printf("* error %d\n", ret);
return ret;
Expand Down
13 changes: 9 additions & 4 deletions piolib/include/rp1_pio_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ struct rp1_pio_sm_xfer_data_args {
uint16_t sm;
uint16_t dir;
uint16_t data_bytes;
uint16_t rsvd;
void *data;
};

struct rp1_pio_sm_xfer_data32_args {
uint16_t sm;
uint16_t dir;
uint32_t data_bytes;
void *data;
};

Expand All @@ -177,10 +185,7 @@ struct rp1_access_hw_args {

#define PIO_IOC_SM_CONFIG_XFER _IOW(PIO_IOC_MAGIC, 0, struct rp1_pio_sm_config_xfer_args)
#define PIO_IOC_SM_XFER_DATA _IOW(PIO_IOC_MAGIC, 1, struct rp1_pio_sm_xfer_data_args)

#ifdef CONFIG_COMPAT
//XXX #define PIO_IOC_SM_XFER_DATA32 _IOW(PIO_IOC_MAGIC, 2, struct pio_sm_xfer_data_args)
#endif
#define PIO_IOC_SM_XFER_DATA32 _IOW(PIO_IOC_MAGIC, 2, struct rp1_pio_sm_xfer_data32_args)

#define PIO_IOC_READ_HW _IOW(PIO_IOC_MAGIC, 8, struct rp1_access_hw_args)
#define PIO_IOC_WRITE_HW _IOW(PIO_IOC_MAGIC, 9, struct rp1_access_hw_args)
Expand Down
8 changes: 6 additions & 2 deletions piolib/pio_rp1.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,14 @@ static int rp1_pio_sm_config_xfer(PIO pio, uint sm, uint dir, uint buf_size, uin

static int rp1_pio_sm_xfer_data(PIO pio, uint sm, uint dir, uint data_bytes, void *data)
{
struct rp1_pio_sm_xfer_data_args args = { .sm = sm, .dir = dir, .data_bytes = data_bytes, .data = data };
struct rp1_pio_sm_xfer_data_args args = { .sm = sm, .dir = dir, .data_bytes = data_bytes, .rsvd = 0, .data = data };
struct rp1_pio_sm_xfer_data32_args args32 = { .sm = sm, .dir = dir, .data_bytes = data_bytes, .data = data };
int err;
check_sm_param(sm);
err = rp1_ioctl(pio, PIO_IOC_SM_XFER_DATA, &args);
if (data_bytes > 0xffff)
err = rp1_ioctl(pio, PIO_IOC_SM_XFER_DATA32, &args32);
else
err = rp1_ioctl(pio, PIO_IOC_SM_XFER_DATA, &args);
return (err > 0);
}

Expand Down

0 comments on commit 3da6b43

Please sign in to comment.