Now I'm questioning what I did then because I just saw the port disappear from lsusb. I never actually confirmed what was connected where. So I may be over there chasing my tail if 40 worked here.
Worth a try.
This makes no sense to me!
That is the Pin Table for the UNOWIFIR4 only goes up to pin 38?
extern "C" const PinMuxCfg_t g_pin_cfg[] = {
{ BSP_IO_PORT_03_PIN_01, P301 }, /* (0) D0 ------------------------- DIGITAL */
...
{ BSP_IO_PORT_04_PIN_08, P408 }, /* (21) USB switch, drive high for RA4 */
...
{ BSP_IO_PORT_02_PIN_06, P206 }, /* (36) D36 */
{ BSP_IO_PORT_02_PIN_12, P212 }, /* (37) D37 */
{ BSP_IO_PORT_02_PIN_13, P213 }, /* (38) D38 */
};
So for example digitalWrite(40, HIGH);
void digitalWrite(pin_size_t pin, PinStatus val) {
R_IOPORT_PinWrite(NULL, g_pin_cfg[pin].pin, val == LOW ? BSP_IO_LEVEL_LOW : BSP_IO_LEVEL_HIGH);
}
Is indexing off into random garbage off of the end of g_pin_cfg array!
And I checked out this table both in the current new release (1.0.4) as well as current sources.
I am confused, how this works!
Thanks, that is a nice switch setup!
However, I personally cheat on this!
I use USB Hubs with power switches. On one computer I have one of these:
https://www.amazon.com/gp/product/B07G8CMR18
And on my other computer one of these:
https://www.amazon.com/gp/product/B08TT1ZK8G
And another vote for pin 21.
I also have a thread that I didn't mark last night that says that pin 21 is how you turn the Tx light on.
I love Arduino documentation!
From variant.cpp:
extern "C" const PinMuxCfg_t g_pin_cfg[] = {
{ BSP_IO_PORT_03_PIN_01, P301 }, /* (0) D0 ------------------------- DIGITAL */
{ BSP_IO_PORT_03_PIN_02, P302 }, /* (1) D1 */
{ BSP_IO_PORT_01_PIN_04, P104 }, /* (2) D2 */
{ BSP_IO_PORT_01_PIN_05, P105 }, /* (3) D3~ */
{ BSP_IO_PORT_01_PIN_06, P106 }, /* (4) D4 */
{ BSP_IO_PORT_01_PIN_07, P107 }, /* (5) D5~ */
{ BSP_IO_PORT_01_PIN_11, P111 }, /* (6) D6~ */
{ BSP_IO_PORT_01_PIN_12, P112 }, /* (7) D7 */
{ BSP_IO_PORT_03_PIN_04, P304 }, /* (8) D8 */
{ BSP_IO_PORT_03_PIN_03, P303 }, /* (9) D9~ */
{ BSP_IO_PORT_01_PIN_03, P103 }, /* (10) D10~ */
{ BSP_IO_PORT_04_PIN_11, P411 }, /* (11) D11~ */
{ BSP_IO_PORT_04_PIN_10, P410 }, /* (12) D12 */
{ BSP_IO_PORT_01_PIN_02, P102 }, /* (13) D13 */
{ BSP_IO_PORT_00_PIN_14, P014 }, /* (14) A0 -------------------------- ANALOG */
{ BSP_IO_PORT_00_PIN_00, P000 }, /* (15) A1 */
{ BSP_IO_PORT_00_PIN_01, P001 }, /* (16) A2 */
{ BSP_IO_PORT_00_PIN_02, P002 }, /* (17) A3 */
{ BSP_IO_PORT_01_PIN_01, P101 }, /* (18) A4/SDA */
{ BSP_IO_PORT_01_PIN_00, P100 }, /* (19) A5/SCL */
{ BSP_IO_PORT_05_PIN_00, P500 }, /* (20) Analog voltage measure pin */
{ BSP_IO_PORT_04_PIN_08, P408 }, /* (21) USB switch, drive high for RA4 */
{ BSP_IO_PORT_01_PIN_09, P109 }, /* (22) D22 ------------------------ TX */
{ BSP_IO_PORT_01_PIN_10, P110 }, /* (23) D23 ------------------------ RX */
{ BSP_IO_PORT_05_PIN_01, P501 }, /* (24) D24 ------------------------- TX WIFI */
{ BSP_IO_PORT_05_PIN_02, P502 }, /* (25) D25 ------------------------- RX WIFI */
{ BSP_IO_PORT_04_PIN_00, P400 }, /* (26) D26 QWIC SCL */
{ BSP_IO_PORT_04_PIN_01, P401 }, /* (27) D27 QWIC SDA */
{ BSP_IO_PORT_00_PIN_03, P003 }, /* (28) D28 */
{ BSP_IO_PORT_00_PIN_04, P004 }, /* (29) D29 */
{ BSP_IO_PORT_00_PIN_11, P011 }, /* (30) D30 */
{ BSP_IO_PORT_00_PIN_12, P012 }, /* (31) D31 */
{ BSP_IO_PORT_00_PIN_13, P013 }, /* (32) D32 */
{ BSP_IO_PORT_00_PIN_15, P015 }, /* (33) D33 */
{ BSP_IO_PORT_02_PIN_04, P204 }, /* (34) D34 */
{ BSP_IO_PORT_02_PIN_05, P205 }, /* (35) D35 */
{ BSP_IO_PORT_02_PIN_06, P206 }, /* (36) D36 */
{ BSP_IO_PORT_02_PIN_12, P212 }, /* (37) D37 */
{ BSP_IO_PORT_02_PIN_13, P213 }, /* (38) D38 */
};
Schematic here:
At the bottom left is the USB switch. The line at the bottom there is labelled P408.
On the chip P408 is USB_ID (really? why'd you use that one?) It's on the left side fourth from the bottom on the RA4M1
In the list, 408 is number 21.
In digital.cpp (no Wiring anymore?):
void digitalWrite(pin_size_t pin, PinStatus val) {
R_IOPORT_PinWrite(NULL, g_pin_cfg[pin].pin, val == LOW ? BSP_IO_LEVEL_LOW : BSP_IO_LEVEL_HIGH);
}
So that array is definitely where our pin number is coming from. And there's no element 40 in it.
Just below the pin table in variant.cpp:
// if _USBStart is called, this will swap the USB port over the ESP one
void configure_usb_mux() {
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_PRC1_UNLOCK;
(*((volatile uint32_t *) &R_SYSTEM->VBTBKR[1])) = 40;
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK;
pinMode(21, OUTPUT);
digitalWrite(21, HIGH);
}
This code and comment claims to use pin 21. But what's it doing in that register with the 40?
It's one of the vbatt backup registers. The User's Manual for the RA4M1 describes it as used to store or restore data.
11.3.4
VBATT Backup Register Usage
The VBATT Backup Register (VBTBKRn), where n = 0 to 511, can be used to store or restore data as described in the
following procedure:
- The VBTCR1.BPWSWSTP bit must be set to 1 if this bit is being accessed for the first time after a power-on reset.
- Wait for the VBTSR.VBTRVLD bit to be 1.
- VBTBKRn, where n = 0 to 511 can be accessed by an 8-bit read or write operation.
- Clear the VBTCR1.BPWSWSTP bit to 0 to enable the battery power switch. See section 11.3.2, VBATT Battery
Power Supply Switch Usage.
I don't see them doing any of those other things. Just writing a 40 for some unknown reason.
I wondered if it was read somewhere at startup or something so I:
:~/.arduino15/packages/arduino/hardware/renesas_uno/1.0.2$ grep -Rnw './' -e 'VBTBKR'
I get a bunch of hits where the register is defined for a bunch of different processors. I get the hit we already have. And I get one more in SerialUSB.cpp:
#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *) &R_SYSTEM->VBTBKR[0]))
grep -Rnw './' -e 'VBTBKR\[1\]'
got only the one we know about from variant.cpp
OK so:
:~/.arduino15/packages/arduino/hardware/renesas_uno/1.0.2$ grep -Rnw './' -e 'BOOT_DOUBLE_TAP_DATA'
And all the results are in SerialUSB.cpp:
#ifdef NO_BACKUP_REGISTERS
#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *)0x20007FF0))
#else
#define BOOT_DOUBLE_TAP_DATA (*((volatile uint32_t *) &R_SYSTEM->VBTBKR[0]))
#endif
#define DOUBLE_TAP_MAGIC 0x07738135
Don't you just love seeing the word MAGIC in code with a random number and no comment!
Whatever it is, it gets written to that register at reset:
static void CheckSerialReset() {
#if NO_1200_BPS_RESET
return;
#endif
if ((_SerialUSB::_bps == 1200) && (! _SerialUSB::_dtr)) {
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_PRC1_UNLOCK;
BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK;
((R_USB_FS0_Type*)R_USB_FS0_BASE)->SYSCFG_b.DPRPU = 0;
NVIC_SystemReset();
while (1); // WDT will fire here
}
}
and another mention in the watchdog reset
extern "C" void tud_dfu_runtime_reboot_to_dfu_cb(void)
{
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_PRC1_UNLOCK;
BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;
R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK;
#ifndef NO_WATCHDOG
wdt_instance_ctrl_t p_ctrl; wdt_cfg_t p_cfg;
p_cfg.timeout = WDT_TIMEOUT_16384;
p_cfg.clock_division = WDT_CLOCK_DIVISION_256;
p_cfg.window_start = WDT_WINDOW_START_100;
p_cfg.window_end = WDT_WINDOW_END_0;
p_cfg.reset_control = WDT_RESET_CONTROL_RESET;
p_cfg.stop_control = WDT_STOP_CONTROL_ENABLE;
int err = R_WDT_Open(&p_ctrl, &p_cfg);
R_WDT_Refresh(&p_ctrl);
is_watchdog_reset_in_progress_for_upload = true;
if (err == FSP_ERR_ALREADY_OPEN) {
// loop here since the watchdog is already being used by the application
// (which will very likely kick it as soon as we return)
while (1);
}
#else
NVIC_SystemReset();
#endif
//while (1);
}
And it's larger than 8 bits so it's going to necessarily write over the next register which is where we put that 40.
So with the 40 there, DOUBLE_TAP_MAGIC becomes: 0x07288135
What that does is anyone's guess.
And I'm stuck. I don't really know where to go from here.
:~/.arduino15/packages/arduino/hardware/renesas_uno/1.0.2$ grep -Rnw './' -e 'D40'
gives no hits at all. There's nothing in there called D40
When I saw all of this before, I wondered if the person writing documentation might have seen the 40 in that configure mux function and just got confused and wrote the wrong number. But now Mike is saying that it switched the mux for him. So I'm completely confused.
Who do we ask next?
This is how religion starts !
Are you suggesting that we appeal to a higher power?
Who is the patron saint of USB?
Maybe this one?
Note that is about the UNO R4 Minima board, not the WiFi. Arduino pin 21 is connected to the "TX" LED on the Minima:
Roger Dodger. That's the one. Thanks.
similarly to on an ESP-01 i guess
Thanks guys you were both right.
I got the scope out and measured the state of the USB select lines, and indeed using pin 21 controlled the line and pin 40 didn't.
However, I still had the same problems in resetting the board.
I remembered something @Delta_G said about the documentation having the wrong pin number and the wrong way up. So instead putting the data select high I put it low, and that was the trick to make it work. If the select line is left high then you do need a double tap on the reset line to get it going again. But when the select line is low, you need a power cycle.
This seemed to make everything work like I said in my solution post #18. I have edited the code in that post to make it reflect the new solution, with a note to say that it was prompted by your posts.
I don't know what pin 40 was doing, as you say it was a mystery.
Has a request been put in to alter the documentation in the cheat sheet? The last time we found an error in that :- thread error in cheat sheet
Then @ksoderby corrected it right away.
So the section USB Bridge that says:-
Software - By pulling D40 to HIGH you will close the circuit that controls which MCU is connected to USB. While D40 is HIGH, the RA4M1 is connected to the USB Serial port, and while D40 is LOW the ESP32 is connected, like the default configuration. You can do this by including the following code in void setup()
> pinMode(40, OUTPUT);
> digitalWrite(40, HIGH);
>
Should actually say:-
Software - By pulling D21 to LOW you will close the circuit that controls which MCU is connected to USB. While D21 is LOW, the RA4M1 is connected to the USB Serial port, and while D21 is HIGH the ESP32 is connected. You can do this by including the following code in void setup()
> pinMode(21, OUTPUT);
> digitalWrite(21, LOW);
>
I have added an Issue in the Error in cheat sheet documentation for UNO R4 WiFi · Issue #1322 · arduino/docs-content · GitHub to cover this.
My suspicion is that this was how some prototypes worked but is not the way the production model works.
I wonder if we shouldn't actually be calling that function from variant.cpp. I just don't know what that magic number 40 is doing and I wonder if it's actually needed.
I hate magic numbers.
Me too!
This feels like throwing darts.
From the schematic:
It appears like that IO pin has a Pull-Down resistor hooked up to it. So setting it low should have no effect.
Sorry I know that it is covered earlier, but it is early in the morning, and I need a lot more to dig through thread, so will ask here.
How exactly are you building and uploading your sketch? Specifically what board type have you defined that is setup for the WIFI, but enables USB and uses the different bootloader?
If for example you are building as MINIMA, then everything we are mentioning about pin numbers and the like is totally bogus, as we are talking about a different pin table.
Instead of:
pinMode(40, OUTPUT);
digitalWrite(40, HIGH);
You might try:
R_IOPORT_PinCfg(NULL, BSP_IO_PORT_04_PIN_08, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinWrite(NULL,BSP_IO_PORT_04_PIN_08, BSP_IO_LEVEL_HIGH);
Which unwinds the code for pinMode and digitalWrite to the specific port/pin and does not rely on the variant pin table.
@ptillisch - do you know if anyone has setup a proper variant for this?
Probably starting up as a copy of the WIFI, but then change the build options to remove the no USB define, plus the upload rules... Alternative might be an option under the WIFI to do this?
4 posts were split to a new topic: Creating variant for using UNO R4 WiFi in USB bridge bypass mode
Why on earth should I do that? I am not a beginner.
To recap, I can get the MIDI library to work on a Minima, no problem. When I try to use it on the WI-FI it crashes and refuses to load on subsequent downloads. In fact it never gets to the upload part citing an error with the serial part not being there. So the boards needs to be somehow recovered before it will work again.
This can be done in two ways
-
A double tap on the reset button
-
A power cycle of the board.
This depends on the state of that USB switch data select.
The problem with 1) is that after the board is recovered then there will not be a serial port created of the correct baud rate to attach to Hairless and will show hairless errors that clearly indicate the baud rate is wrong.
This doesn't happen with method two.
I am very aware of the schematic and I used it to probe the board on an oscilloscope and confirm that magic number 40 did not switch the select line of the USB but magic number 21 did switch it. This allowed the recovery of the board using a power cycle which did produce a serial port with the correct data rate.
I feel I am being sniped at for experiment and finding out what works and what does not. I am a hardware guy, with a scope, following the instructions in the documentation, which appeared to be wrong both in pin number and logic level.
If you want to help tell me what will work rather than saying you don't understand what is happening and blaming me for your lack of understanding.
In my opinion then the information in the online documentation is clearly wrong. And I have proposed how it should be changed. There is a lot of "flying by the seat of your pats" with these two boards. Am I supposed to give up on these boards and wait for someone to get the document right? That has never been my attitude.
If you have a problem with this then please make a positive contribution like you often do.
Sorry, if I was sounding negative. It was not my intention. I in no way believe you are a beginner, after all you have a Karma > 2500, so you have been around the block!
If the host side does do things like change the BAUD rate, then I can see where there would be problems with the WIFI boards. That is, as I mentioned in a thread I opened:
USB Serial - differences between WIFI and MINIMA - UNO R4 / UNO R4 WiFi - Arduino Forum
There is no mechanism that I could find, where the ESP32 processor when it detects that host wants to change something like the baud rate, for the main processor to know about this. It probably just changes the baud rate of it's UART, but nothing changes it on the main processors side.
I was trying to get a better understanding of which setup are we talking about. I remember a recent thread on someone setting up to use the USB of the processor instead of the ESP32 and flashing the processor with a different bootloader...
And I was trying to make sure this was not the case here.
Then wondering how you have it building with USB code. That is if I wanted to experiment with the board in a similar state what do I need to do?
The boards.txt for the WIFI has:
unor4wifi.build.defines=-DF_CPU=48000000 -DNO_USB -DBACKTRACE_SUPPORT -DARDUINO_UNOR4_WIFI
Could potentially edit this and remove the -DNO_USB
Not sure if that is all that is needed or not?
Edit:
Probably would need to update things like in Arduino.h
#ifndef NO_USB
#define Serial SerialUSB
#define Serial1 _UART1_
#define Serial2 _UART2_
#define Serial3 _UART3_
#define Serial4 _UART4_
#define Serial5 _UART5_
#else
#define Serial _UART1_
#define Serial1 _UART2_
#define Serial2 _UART3_
#define Serial3 _UART4_
#define Serial4 _UART5_
#endif
As for why 40 might work? No idea, maybe the junk it loaded after the end of the table either by luck reset something or faulted the processor...
As for the main problem, of not being able to download after, without power cycle or the like, as you already know it could turn out to be a PIA to debug what is going on.
a) bootloader issue?
b) Software on PC that wants to talk to bootloader?
c) Host machine getting confused?
It might require something like a USB analyzer to try to see what is happening. I have debugged some USB issues like this with my Logic Analyzer, but a pain and it can not handle high speed mode (480mbs), but I don't think these boards USB run that anyway.
Again sorry.
OK.
There is a big problem with both the R4 boards and serial ports on IDE 1.8.19. This, I understand, is because this is handled by Java. The result is that you have a great of difficulty using the normal serial print debug method. I believe there is a outstanding "issue", yet to be resolved.
Therefore I am trying to recover a board when it is "broken", which I believe should not happen at all, but the fact is that it does happen.
My main guide is this book :-
Rather than wait around waiting for something that, I suspect is, of very little interest to those pushing IDE2.x.
My main interest in this thread was to discover it the MIDI-Library could be made to work on these two new processors. Having succeeded with the Minima the WIFI would fail and "trash" the board for future downloads. If the R4 software were up to snuff I am sure this would not happen. But is does.
Awesome.
So I wonder what happens when we use a pin number outside the array. Running off the end of an array if never good.
In the standard avr core in wiring_digital.c
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
Note how it checks to see if the pin number is valid or not and simply returns if it isn't.
Should the digitalWrite function in the R4 core do the same thing? It seems like it would be a good idea unless we're 100% certain that what's beyond that array can never be mistaken for a pin number by the FSP code.
Thanks but the simple fact is that the documentation says writing to pin 40 will switch the USB select line. Observations with an oscilloscope show this to be incorrect. Observations with a scope also show that is the case when using pin 21. Which are inline with the methods of my "guide book".
So on a simple matter of fact the documentation is wrong and needs correcting. What writing to pin 40 actually does is of little interest to me when tackling my problem.