Custom pcb P214 port reading

Hello Everyone.
I made a custom minima, where I use more I/O port, especially the P214 and P215 port.

So to be able to use arduino function like digitalRead() and others, I modified theses files :
Variant.cpp -> I added

...extern "C" const PinMuxCfg_t g_pin_cfg[] = { 
...
  { BSP_IO_PORT_02_PIN_15,    P215   }, /* (27) DI100 */
  { BSP_IO_PORT_02_PIN_14,    P214   }, /* (28) DI101 */
}

pins_arduino.h -> I added

static const uint8_t D100 = 27u;
static const uint8_t D101 = 28u;

And pinmux.inc -> I added to avoid compilation error

const uint16_t P214[] = {
PIN_PWM|CHANNEL_0|LAST_ITEM_GUARD
};

const uint16_t P215[] = {
PIN_ANALOG|CHANNEL_0|LAST_ITEM_GUARD
};

My sketch compile and upload to the pcb without error, but when I try to read something on D100 or D101, nothing happens.

So I'm sur that my pinmux.inc P214 and P215 I added is badly written
I already tried other configuration (like changing PIN_PWM by PIN_ANALOG or try different CHANNEL), but same result, I can't read these ports state.

Can someone please knows the right code to put on pinmux for P214 and P215 ? My programmation level is too low for finding that.
Description of these PORT p.69 (1.3) of renesas a4m1 datasheet.

Thanks

Nobody to help me ? :sleepy:

Pinmux information is not used for normal/standard GPIO access.

If you do pinMode(D100, INPUT), in cores/arduino/digital.cpp it will look for offset D100 (27) and read the pin : BSP_IO_PORT_02_PIN_15. The later is defined in bsp_io.h for the variant as 0x020E. That is sent to the FSP routine R_IOPORT_PinCfg(). digitalRead() works in the same manner. You could try to copy that lookup in a sketch and see whether that works.

D214 and D215 are special GPIO's and that might be part of your issue: Look in the datasheet at :

Chapter 19.2.1 Port Control Register 1 (PCNTR1/PODR/PDR): P200, P214, and P215 are input only, so PORT2.PCNTR1.PDR00, PORT2.PCNTR1.PDR14, and PORT2.PCNTR1.PDR15 are reserved.

Chapter 19.4 I/O Ports Handling of Unused Pins. There is mention about the special handling.

Table 19.9 Register settings for input/output pin function (PORT2) (2). No extra functions for P214 and P215

thank you @paulvha for your response.

I already try to use directly the

with the right P214 or P215 adress, but without success.

I already read all this, but because

P214, and P215 are input only

I hoped that we can nevertheless read this pin and nothing else than that.

But the other description make me doubt about it, so thats why I hoped someone to clarify it definitely

As got interested I spent a bit more time trying to understand what was going on and maybe a clue.

I created a sketch to help analyzing and can set and display the detailed settings of the different pins on the different ports. I have attached that so you can check the values.
SetReadPin.ino (10.8 KB)

I found forum posts; https://community.renesas.com/mcu-mpu/ra/f/forum/17496/cannot-read-pin-p214-p215-at-ra2l or Cannot read pin - Forum - Renesas Synergy™︎ Platform - Renesas Engineering Community.

Seems "You need to set Sub Oscillator Populated to "Not populated"

Looking in the config file bsp_cfg.h

#ifndef BSP_CLOCK_CFG_SUBCLOCK_POPULATED
#define BSP_CLOCK_CFG_SUBCLOCK_POPULATED (1)
#endif

So maybe it is related to that.

Thank you paulvha for taking the time to write and try this code.
Unfortunaly, your code doesn't take into account P214 and P215, so I wrote a small code to test your last suggestion :

And guess, what ? It WOOOORRRKKKKSSSSS !!!!

I only modify the bsp_cfg.h by changing 1 to 0 inside the #define BSP_CLOCK_CFG_SUBCLOCK_POPULATED (1)

But very important, it only works when SOSCCR_SOSTP is set to 1.

So problem solved, thanks again !

COOL, great to hear!! Thanks for sharing.

Understand completely why the SOSCCR_SOSTP has to be set to 1: to stop it ! On the original/previous l schematics of the Minima there was hardware connected.

I don't expect you need to set BSP_CLOCK_CFG_SUBCLOCK_POPULATED to 0 in the bsp_cfg.h. That file is more a reflection on what was used during building the library libfsp.a and thus enabling SOSCCR_SOSTP

P.s. Indeed my sketch only takes into account the pins that are set in table g_pin_cfg, defined in the file variant.cpp

Okay ! I didn't know that also, thanks

But I wish I can modify a file (like the bsp_cfg one) to automaticcaly set this SOSCCR_SOSTP to 1 ! Initially, this register had to be 1 after reset (reneses datasheet section 8.2.7).
So I think arduino set it automatically to 0 during uploading a sketch

I wasn't able to find what file I can modify for restoring the initial SOSTP reset value...

It is not that easy. Look online GitHub - arduino/ArduinoCore-renesas, there is a README.md. In there are instructions on how to build a new libfsp.a.

With e2studio there is an option to customize and build a new libfsp.a for your board. I have tried to build it without making any changes a month ago.. but got errors and did not find the time since to deep dive.

Okay.
I'm a programmer beginner so it won't be easy for me to go deep dive like you ^^
Can you please tell what's the aim of this libfsp.a ? what is the purpose of creating a new one ?
Don't we need to make a new bootloader for modifying such parameter ? (SOSCCR_SOSTP)

Let me try to make a very SIMPLE (it is a"little" more complex):

There is a large amount of source code that needs to be compiled to get to the final binary code of a sketch that a processor can execute. So much code that can take a (frustrating) very long time with every compilation of a sketch.

To reduce that time (but also for other reasons) a large portion that is not expected to change with each sketch is pre-compiled and added as an archive ( or .a file). There are header files ( .h files) that contain information on how this pre-compiled code is customized and can be used in the right way. bsp_cfg.h is such an information file, but there are many others. Changing a header file AFTER the pre-compile, will NOT change the pre-compiled archive, it just changes (wrongly) what the pre-compiled code looks like.

The relevant parts of a pre-compiled archive are included, linked, during one of the last stages of compiling the sketch. The libfsp.a contains the inner core, low level, pre-compiled routines of which the relevant parts are included in final binary code of a sketch. That final code is then loaded by the bootloader in the flash memory of the processor to be executed.

So a new libfsp.a could include different customization, bug fixes and/or new features. The header files would then reflect those changes.

A new bootloader is not needed. A bootloader (again simple put) loads the new compiled sketch binary code in flash and/or starts the binary sketch code that is in flash memory.

I was afraid of these explanation and I was right lol.
I do understand your explanation, but I wish I can understand all the mecanism, how the arduino system use all these files (edition, copy, read header file, which files are analyses at first before others, etc) before building the micro hex file... my goal to make a custom board which can be easily programmed by the arduino ide.

Maybe can you advice me some links to learn how all this work ?

Thanks again for your help

I posted a new patch in this PR , feel free to test and comment on github :slight_smile:
Thanks everyone for the deep debugging session!

Thank you for that @facchinm
I see that you add some new function, what is the purpose of the usb_post-init()?
And where is it called to be sure they are used at the board startup ?

void usb_post_initialization() {
  ((R_USB_FS0_Type*)R_USB_FS0_BASE)->USBMC_b.VDCEN = 1;
}
void initVariant() {
  // bootloader configures LED_BUILTIN as PWM output, deconfigure it to avoid spurious signals
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(3, PIN_CFG_REQ_PWM)[0]));
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(5, PIN_CFG_REQ_PWM)[0]));
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(6, PIN_CFG_REQ_PWM)[0]));
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(9, PIN_CFG_REQ_PWM)[0]));
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(10, PIN_CFG_REQ_PWM)[0]));
  FspTimer::set_initial_timer_channel_as_pwm(GPT_TIMER, GET_CHANNEL(getPinCfgs(11, PIN_CFG_REQ_PWM)[0]));
}