Set pinmux to PRU Industrial Ethernet Peripheral (IEP) from Linux

Is there a way to set the pinmux for a pin to the PRU Industrial Ethernet Peripheral from Linux (for example: set pin P9_17 to pr1_edio_data_out0)?

If not, what would be the recommended way to do so?

Thanks.

As far as I can tell, the old mmap() method fails. What’s my next step?

`
#include <stdint.h>

#include <stdio.h>
#include <stdlib.h>

#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <assert.h>

#define CONTROL_MODULE_START ((uint32_t)0x44E10000)
#define CONTROL_MODULE_END ((uint32_t)0x44E11FFF)
#define CONTROL_MODULE_LENGTH (CONTROL_MODULE_END - CONTROL_MODULE_START + 1)

// Official pin name for pr1_edio_data_out0 is SPI0_D1 in Mode 6
// Official pin name for pr1_edio_data_out1 is SPI0_CS0 in Mode 6

#define CONF_SPI0_D1_OFFSET 0x958
#define CONF_SPI0_CS0_OFFSET 0x95C

#define MODE_1 0x1
#define MODE_4 0x4
#define MODE_6 0x6

int main(int argc, char *argv[])
{
uint32_t volatile * control_mode_mapped_base = NULL;

int fd = open("/dev/mem", O_RDWR);
printf("/dev/mem opened: %d\n", fd);
printf(“Mapping %X - %X (size: %X)\n”, CONTROL_MODULE_START, CONTROL_MODULE_END, CONTROL_MODULE_LENGTH);

uint32_t volatile * const control_module_mapped_base = mmap(NULL, CONTROL_MODULE_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, CONTROL_MODULE_START);
printf(“Mapped base to: %p\n”, control_module_mapped_base);
assert(control_mode_mapped_base != ((uint32_t volatile * const)(-1)));

uint32_t volatile * const u32_control_P9_17 = (control_module_mapped_base + (CONF_SPI0_CS0_OFFSET/4)); // / 4 is due to the way C handles a pointer to uint32_t
uint32_t volatile * const u32_control_P9_18 = (control_module_mapped_base + (CONF_SPI0_D1_OFFSET/4));

*u32_control_P9_17 = MODE_1; // Fails to write
*u32_control_P9_18 = MODE_1;

printf(“Mode for P9_17: %X\n”, (*u32_control_P9_17 & 0x7)); // Read is fine–config-pin will cause this to change apropriately
printf(“Mode for P9_18: %X\n”, (*u32_control_P9_18 & 0x7));

assert((*u32_control_P9_17 & 0x7) == MODE_1);
assert((*u32_control_P9_18 & 0x7) == MODE_1);

munmap((void *)control_mode_mapped_base, CONTROL_MODULE_LENGTH);

close(fd);
}

`

No way! P9_17 is for PRU-1.

But libpruio can set P9_18 to pr1_edio_data_out0, which is mode 6. Find example code at http://users.freebasic-portal.de/tjf/Projekte/libpruio/doc/html/pruss__toggle_8c_source.html

In your case it needs a line at line number 110 like

`
if (io->setPin(io, P9_18, 6)) {
printf(“P9_18 configuration failed (%s)\n”, io->Errr); break;}

`

OR a resistor to the mode, if needed.

Regards

I forgot to mention:

If you want to use that pin for tri-state (as discussed in an other thread), you’ve to enable the receiver as well

`
if (io->setPin(io, P9_18, 6 | PRUIO_RX_ACTIV)) {
printf(“P9_18 configuration failed (%s)\n”, io->Errr); break;}

`

Well, sort of, except you omit the EXTREMELY important point that you install a custom kernel module in order to expose the clock activation and pinmux system to all users.

Okay, yes, if I build a kernel module I now have full access to all registers on the system with no restrictions. That’s sort of like swatting a fly with an H-Bomb, but it will work.

This means that config-pin has a fairly significant bug in not being able to route the IEP pins. Has that bug ever been filed anywhere?

Well, sort of, except you omit the EXTREMELY important point that you install a custom kernel module in order to expose the clock activation and pinmux system to all users.

That’s not correct. Only users with write access to the sysfs entry can pinmux. By default that’re members of the pruio system group.

Okay, yes, if I build a kernel module I now have full access to all registers on the system with no restrictions. That’s sort of like swatting a fly with an H-Bomb, but it will work.

It was your idea to use the PRU-IEP module. I recommended to use a pin on a GPIO-SS. Yet, you didn’t explain why the L3/L4 latency isn’t aceptable for your target.

This means that config-pin has a fairly significant bug in not being able to route the IEP pins. Has that bug ever been filed anywhere?

config-pin isn’t able to set lots of useful pin configurations, and has lots of bugs. Ie. you can set GPIO for P9_42 and P9_92 in oposite output states and damage the CPU. C. Steinkuehler didn’t develop that tool with a standard solution in mind. At the beginning it was a work-aroung, and only cosmetic changes were done.

Anyway, you can pinmux at boot-time by writing, compiling and installing a customized device tree overlay. The tool libpruio: src/config/dts_custom.bas File Reference may be helpful in that case.

BTW:

and merged: https://github.com/rcn-ee/libpruio/commits/master

Should have updated v4.14/v4.19/v5.4 kernels this week..

Regards,

Okay, then I’m just missing something obvious. What is a GPIO-SS? What unit and what register address? I see no mention of “GPIO-SS” anywhere in the AM335x Technical Reference Manual.

Normally, I associate SS with “slave select” which means SPI. I see that you can turn around the CS lines on the McSPI subsystem, but you have to switch from Master to Slave Mode. That doesn’t seem like what you are suggesting.

SS=subsystem → chapter 25

Thank you.