arduino / ArduinoCore-mbed

347 stars 203 forks source link

Feature Request: Solution video to unbrick the Portenta Orange LED of Hell #608

Closed hpssjellis closed 1 year ago

hpssjellis commented 1 year ago

Feature Request: Solution video to unbrick the Portenta Orange LED of Hell

P.S. I don't see the Orange LED as bad, I see it as a kind of fuse that protects the Portenta from bad connections. Other micro-controllers without this feature might just break instead of going into the "Orange LED of Hell" mode. My goal is to make this issue easy to solve using regular hardware. Any suggestions would be appreciated.

It seems that there is a high rate of "bricking" for the Arduino PortentaH7 boards being used in a robotics class, with an average of ~14% or (1 in 7 ) of boards becoming permanently stuck in an "Orange LED" state. The request is for a simplified method or video that can help users unbrick their devices, especially for those who may not have access to all the necessary debugging equipment or software. Additionally, it would be helpful to understand the root cause of the issue and why the PMIC controller is losing the ability to control the 3.3V voltage. The requestor is willing to make a video and provide software if a simplified method can be found. Below are links to forum discussions about the issue.

Issue background:

For my Robotics class I have 21 PortentaH7 and over 2 years 3 are now permanently showing the onboard Orange LED (of Hell). One of my after school students has now got his PortentaH7 with the Orange LED.

Some issues seem to be solved by just connecting another 3V3 from another board to the portenta 3V3 (and GND) then burning the Portenta bootloader. (I wish that worked but doesn't seem to for me) Other solutions seem to be using 2 Portenta with breakout boards and manually loading the PMIC code, then flashing the firmware.

Best Forum discussions 1 here and 2 here

but other discussions about it 3 4 5 6 7

hpssjellis commented 1 year ago

A possible starting point would be to upload to the main MBED repository a .hex bootloader for the Portenta. I have tried making one myself but am never sure if it is correct. The Nano33Ble, edgeControl and Nicla all have official .hex files

https://github.com/arduino/ArduinoCore-mbed/tree/master/bootloaders

akash73 commented 1 year ago

hi @hpssjellis all the forum discussion linked, make use of different tools beside the standard usage of Arduino Tools. This of course is possible and doable, but are at own risk , as you can understand.

would you mind recap the scenario to better understand what's happening? which tools are you using, what was your goal ? we can also try to provide some helpful documentation.

regarding this "One of my after school students has now got his PortentaH7 with the Orange LED." : if the board arrived defective (DOA) , please contact our support to solve . thanks!

hpssjellis commented 1 year ago

@akash73 Hi Andrea.

My student was doing his own soldering perf board with the Portenta so easily could have made a short circuit causing the Orange LED. My 3 Orange LED boards are probably from students connecting Robotics equipment wrong or just my own hacking and making mistakes. I am kind of letting my after school group do most of the research, I have only tried some simple techniques so far such as powering the Portenta 3V3 using a different Portenta 3V3 and GND. No effect on the orange LED.

I have a Particle Debugger, a J-LinkV2 Educ Mini JTAG and an St-LinkV2. I do not do a lot of work with debuggers so even setting them up is a bit of a challenge.

So far I have got the particle debugger to upload boot.hex files to a nano33BleSense and it worked, but when I try to make my own Portenta .hex file it seems like it is corrupted. The Particle debugger is drag and drop and the cables it comes with connects nicely to the Ethernet Vision shield which has a few pins cut properly. The LoRa vision shield JTAG connector and breakout board has all 20 pins so a few would need to be cut for the 10 pin cable to fit.

This would be the best solution for my students as it does not need any software installation.

The J-LinkV2 Educ Mini JTAG does actually work to upload a Portenta Bootloader to the Portenta, using the same cable as the Particle Debugger. That is a good start, but now on an orange LED Portenta I get no connection so this setup can work, but not for this case without doing some of the more advanced methods mentioned in the fourms.

It took us a while to figure out that the unlicensed student version was needed and then things worked fine. The student version is installed with the Jlink Segger download but you have to find it.

The Segger software is here https://www.segger.com/downloads/jlink/

My St-LINKV2 does not have the correct cable to connect to the Portenta. I have ordered cables and the conversion board. They are in the mail. I assume this might work for installing the bootloader but we will still have the serial connection issue linked to the Orange LED.

The breakout board is supposed to allow a USB to computer connection to burn the bootloader from the Arduino IDE but I have never got that working. That would be the easiest solution.

In one of the forums this code looks promising https://forum.arduino.cc/t/portenta-h7-bricked/1008494/2 , but I have not tried it yet.

#include <Wire.h>

const int nMichele = 12;//13;
uint16_t regAddrMichele[nMichele] = {0x4f, 0x50, 0x4c, 0x4d, 0x52, 0x53, 0x9c, 0x9e, 0x42, 0x94, 0x3b, 0x35};//, 0x42};
byte     regValMichele[nMichele]  = {0x00, 0x0f, 0x05, 0x03, 0x09, 0x0f, 0x80, 0x20, 0x02, 0xa0, 0x0f, 0x0f};//, 0x01};

const int nTJaekel = 160;
byte regValTJaekel[nTJaekel] = 
 {0x7c ,0x00 ,0x11 ,0x00 ,0x00 ,0x00 ,0x88 ,0x00 ,0x00 ,0x07 ,0x00 ,0x04 ,0x07 ,0x04 ,0x00 ,0x03
 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x07 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
 ,0x00 ,0x05 ,0x00 ,0x00 ,0x00 ,0x3f ,0x00 ,0x00 ,0x08 ,0x1f ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
 ,0x00 ,0x00 ,0x06 ,0x06 ,0x06 ,0x0f ,0x00 ,0x00 ,0x0a ,0x0a ,0x0a ,0x0f ,0x00 ,0x00 ,0x0d ,0x0d
 ,0x0d ,0x03 ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x05 ,0x03 ,0x00 ,0x00
 ,0x0f ,0x00 ,0x09 ,0x0f ,0x00 ,0x00 ,0x00 ,0x00 ,0x21 ,0x80 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01
 ,0x02 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x0c ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00
 ,0x68 ,0x00 ,0xff ,0x00 ,0xac ,0x00 ,0x20 ,0x03 ,0x04 ,0x02 ,0x00 ,0x00 ,0x00 ,0x40 ,0x05 ,0x6b
 ,0x00 ,0x00 ,0x00 ,0x00 ,0xa0 ,0x06 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x80 ,0x00 ,0x20 ,0x00};

uint16_t regAddrTJaekel[nTJaekel] = {
   0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  10,11,12,13,14,15,16,17,18,19,
  20,21,22,23,24,25,26,27,28,29,
  30,31,32,33,34,35,36,37,38,39,
  40,41,42,43,44,45,46,47,48,49,
  50,51,52,53,54,55,56,57,58,59,
  60,61,62,63,64,65,66,67,68,69,
  70,71,72,73,74,75,76,77,78,79,
  80,81,82,83,84,85,86,87,88,89,
  90,91,92,93,94,95,96,97,98,99,
  100,101,102,103,104,105,106,107,108,109,
  110,111,112,113,114,115,116,117,118,119,
  120,121,122,123,124,125,126,127,128,129,
  130,131,132,133,134,135,136,137,138,139,
  140,141,142,143,144,145,146,147,148,149,
  150,151,152,153,154,155,156,157,158,159
};

const byte one = 0x01;
const byte zero = 0x00;
const byte sendRestart = false;

void readI2C(byte devAddr, int m, int n)
{
  Serial.println();
  for (int i = 0; i < m; i++)
  {
    Serial.print(byte(i*16), HEX);
    Serial.print(" | ");
    for (int j = 0; j < n; j++)
    {
      Wire.beginTransmission(devAddr);
      int nWritten = 0;
      nWritten += Wire.write(uint16_t(i*16+j));
      int error = Wire.endTransmission(sendRestart);
      if (error != 0)
      {
        Serial.print("Transmission error, code = ");
        Serial.println(error);
      }
      int nRead = Wire.requestFrom(devAddr, one);
      if (nRead == 1)
      {
        byte valRead = Wire.read();
        Serial.print(valRead, HEX);
        Serial.print(" ");
      }
    }
    Serial.println();
  }
}

void writeI2C(byte devAddr, uint16_t regAddr[], byte regVal[], int n)
{
  Serial.println();
  for (int i = 0; i < n; i++)
  {
    Wire.beginTransmission(devAddr);
    int nWritten = 0;
    nWritten += Wire.write(regAddr[i]);
    nWritten += Wire.write(regVal[i]);
    int error = Wire.endTransmission();
    if (error != 0)
    {
      Serial.print("Transmission error, code = ");
      Serial.println(error);
    } else {
      Serial.print("Wrote ");
      Serial.print(nWritten);
    }
    Wire.beginTransmission(devAddr);
    nWritten = 0;
    nWritten += Wire.write(regAddr[i]);
    error = Wire.endTransmission(sendRestart);
    int nRead = Wire.requestFrom(devAddr, one);
    if (nRead == 1)
    {
      byte valRead = Wire.read();
      Serial.print(" bytes to register ");
      Serial.print(regAddr[i], HEX);
      Serial.print(": wrote ");
      Serial.print(regVal[i], HEX);
      Serial.print(", read ");
      if (valRead != regVal[i]) {
        Serial.print(valRead, HEX);
        Serial.println(" *** ERROR ***");
      } else {
        Serial.println(valRead, HEX);
      }
    } else {
      Serial.print("Error in reception, bytes received = ");
      Serial.println(nRead);
    }
  }

}

void scanI2C() {
  byte error, address;
  int Devices;
  Serial.println();
  Serial.println("I2C Scanner");
  Serial.println("Scanning...");
  Devices = 0;
  for(address = 1; address < 127; address++ )
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
      Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
      Devices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
      Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (Devices == 0)
    Serial.println("No I2C devices found");
  else
    Serial.println("done");
}

void setup() {
  Serial.begin(9600);

  scanI2C();
  Wire.begin();
  Wire.setTimeout(1000);
  byte devAddr = 0x08;
  readI2C(devAddr, 16, 16);
  //writeI2C(devAddr, regAddrMichele, regValMichele, nMichele);
  writeI2C(devAddr, regAddrTJaekel, regValTJaekel, nTJaekel);
  readI2C(devAddr, 16, 16);
}

void loop()
{
  scanI2C();
  delay(5000);          
}

If I can get the ST-link working I will try the above code with the I2C connection using a second Portenta.

I have made my own Portenta HD Dev PCB board which I just got yesterday so that might help with connecting the ST-Link since the JTAG Pins are as follows: J1-73(reset), J1-75(SWDIO-PA13), J1-77(SWCLK-PA14), J1-79(SWO-PB3)

Problem here is my shaky hands soldering those HD connectors. My first attempt the back vision shield is not yet working.

20230125_141921

20230125_141838

Any other suggestion?

hpssjellis commented 1 year ago

I want to split this issue into 2 problems: 1 the orange LED how to return power

  1. How to re-format the bootloader. (This I have solved with the Segger software.

So the PMIC controller. There is the code above and then another code snippet from

https://forum.arduino.cc/t/portenta-h7-bricked/1008494/16

/* Portenta H7 PMIC I2C recovery */
int PMIC_Recover(void)
{
/* slave address PMIC */
#define PMIC_I2C_SLAVE_ADDR (0x08 << 1)

    //check if we can read the PMIC ChipID (should be 0x7C)
    uint8_t data[2];
    int err;

    err = I2CUser_MemReadEx(PMIC_I2C_SLAVE_ADDR, 0, data, 1);
    if (err)
        return err;             //ERROR

    if (data[0] != 0x7C)
    {
        print_log(UART_OUT, "*E: external PMIC not found\r\n");
        return 0;               //ERROR - incorrect ChipID
    }

    //initialize the PMIC registers:
    // LDO2 to 1.8V
      data[0]=0x4F;
      data[1]=0x0;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      /* ATTENTION: if I write this register - the I2C is dead, read ChipID does not work anymore
       * write this register as the last one!
       */
#if 0
      data[0]=0x50;
      data[1]=0xF;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));
#endif

      // LDO1 to 1.0V
      data[0]=0x4c;
      data[1]=0x5;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      data[0]=0x4d;
      data[1]=0xF;      //was 0x3
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      // LDO3 to 1.2V
      data[0]=0x52;
      data[1]=0x9;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      data[0]=0x53;
      data[1]=0xF;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      osDelay(10);

      //charger LED off - duty cycle
      data[0]=0x9C;
      data[1]=(1 << 7);     //0x80
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      // Disable charger led
      data[0]=0x9E;
      data[1]=(1 << 5);     //0x20
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      osDelay(10);

      // SW3: set 2A as current limit
      // Helps keeping the rail up at wifi startup
      data[0]=0x42;
      data[1]=2;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      osDelay(10);

      // Change VBUS INPUT CURRENT LIMIT to 1.5A
      data[0]=0x94;
      data[1]=(20 << 3);        //0xA0
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      // SW2 to 3.3V (SW2_VOLT)
      data[0]=0x3B;
      data[1]=0xF;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

      // SW1 to 3.0V (SW1_VOLT)
      data[0]=0x35;
      data[1]=0xF;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));

#if 1
      osDelay(10);
      data[0]=0x50;
      data[1]=0xF;
      I2C1_Write(PMIC_I2C_SLAVE_ADDR, data, sizeof(data));
#endif

      return 0;     //OK
}

Question: Do you really need the breakout board for this. Cant the main I2C0 `MbedI2C myI2C0(PH_8, PH_7); from one portenta connect to the same I2C on the other portenta? How would I change the code?

Any opinion on the 2 codes I posted. The second one looks like a function not an entire sketch.

This image at https://forum.arduino.cc/t/orange-led-of-hell/926639/34 is very interesting

image

and this one

image

image

hpssjellis commented 1 year ago

Here are some ST-Link V2 instructions which I will try when my cable conversion board arrives, but as I have mentioned this only allows the bootloader to be reformatted probably does not do anything for the Orange LED:

Requirements:

STLINK programmer for STM32
STM32Cube Programmer software
Portenta H7
Portenta Breakout Board or alternative way to expose the JTAG pins from the high density connectors
Bootloader file (.bin or .elf). Download available from GitHub ArduinoCore-mbed repository.

Instructions:

Connect your Portenta H7 to the Breakout board and power via USB.
Connect the STM programmer to your PC via USB and to the JTAG connector on the Portenta Breakout.
Open STM32Cube and click on the 'connect' green button to establish connection between the PC and the programmer
(upgrade firmware if necessary).
Head over the icons on the left hand side and click 'Erasing and Programming' icon (marked with an orange rectangle in the image below).
Load the bootloader file.
Click 'Start Programming' button.

image


If programming was successful the following message will show up: "File download complete". | If programming was successful the following message will show up: "File download complete".
hpssjellis commented 1 year ago

I get that 2 portenta can't use the same I2C channels to communicate and that is why you need the breakout board, but a different Arduino MBED board like the niclaVision or Nano33Ble might use a different set of pins than the Portenta for its main I2C channel. Also before writing over the PMIC controller I would like to verify what is stored for the PMIC boot area. That shoukd be a simple program running from the other board that first check a good portenta and then checks a portenta with the Orange LED just showing the main PMIC boot data would be very useful in classifying or understanding the issue. Any suggestions for a sketch that would do that. I guess I will try chatGPT.

hpssjellis commented 1 year ago

ChatGPT's reply # Screenshot_20230128_094815_Chrome

hpssjellis commented 1 year ago

This forum post looks useful

https://forum.arduino.cc/t/help-using-i2c-to-read-a-register-value/641465/8

Updat to what I am trying, people who know what they are doing can submit sketches please.

  1. Make a sketch that on a good Portenta simply writes the PMC correct bytes. Not even sure if this needs I2C. Can't I easily read a group of register values ?
  2. write a good Portenta sketch that uses the breakout board and I2C to check the PMIC values.
  3. Write I2C code that uses a different Arduino MBED board (Nano33Ble, Nicla, RP204 Connect) that uses a different I2C pin to send and receive so you can connect to the Portenta without the breakout board and read the PMIC on both a good and bad (orange LED) Portenta.
  4. Same as above but fixes the bad PMIC. If anyone knows how to write any of these sketches please paste here. I have never worked with registers but it should be fun to learn.
hpssjellis commented 1 year ago

So I am making some headway.

My Code will be at this repository folder

https://github.com/hpssjellis/my-examples-for-the-arduino-portentaH7/tree/master/research/i2c-orange

A04 allows scanning of the second portenta for any avaliable I2C channels.

Weird finding is that only I2C 1 works and I2C 0 and 2 doesn't for me.

I connect GND, D11 (SDA) and D12 (SCL) on the master Portenta and on the portenta with breakout board I connect GND and SDA1 and SCL1 and that works. But connecting sda0 and scl0 or sda2 and scl2 does not seem to work.

No worries since one working seems to be enough

A06 allows reading 16 x 16 bytes from the address given in this case 0x08000000 . Look at the readme.md file as I have shown the difference between the Working Portenta and a Orange LED Portenta. only a few small differences.

hpssjellis commented 1 year ago

This is a bit worrisome. Following is a comparison of the PMIC fix listed in the code at the top of this page, and the second is the data I get from a working PortentaH7 (I hope it is not an H7Lite I accidentally purchased a few of those)

Any suggestions why the differences @facchinm ? Is it possible that the original fix was for an older bootloader and this is a new bootloader PMIC area?

image

And here is a comparison between my working PortentaH7 and the Orange LED Portenta (ignore the bad formatting and the extra ,0x at the end of each row) image

hpssjellis commented 1 year ago

@facchinm @akash73 @pnndra @sebromero

As soon as an engineer has a look at this, I think I can close this issue. I made an app a12-full-app-orange-led-fix.ino Which first checks for an I2C or multiple I2C connections to a device. Then on user input of a 'Y' either prints the PMIC area or prints it, changes it and then prints it again.

This app can reset the Orange LED and then you need to use a debugger to reset the bootloader, but I feel the following code could be a bit better if an engineer has a look at it. The main parts are at about line 240:

        writeI2cRocksetta(devAddr, 0x4f, 0x0);// LDO2 to 1.8V //initialize the PMIC registers:
        writeI2cRocksetta(devAddr, 0x4c, 0xf);// LDO1 to 1.0V
        writeI2cRocksetta(devAddr, 0x4d, 0xf);
        writeI2cRocksetta(devAddr, 0x52, 0x9);// LDO3 to 1.2V
        writeI2cRocksetta(devAddr, 0x53, 0xf);
        osDelay(10);
        writeI2cRocksetta(devAddr, 0x9c, (1 << 7) );//0x80 //charger LED off - duty cycle
        writeI2cRocksetta(devAddr, 0x9e, (1 << 5) );//0x20 // Disable charger led
        osDelay(10);
        writeI2cRocksetta(devAddr, 0x42, 2);    // SW3: set 2A as current limit // Helps keeping the rail up at wifi startup
        osDelay(10);
        writeI2cRocksetta(devAddr, 0x94, (20 << 3) );//0xA0 // Change VBUS INPUT CURRENT LIMIT to 1.5A
        writeI2cRocksetta(devAddr, 0x3b, 0xf);// SW2 to 3.3V (SW2_VOLT)

        /* ATTENTION: if I write this register - the I2C is dead, read ChipID does not work anymore
         * write this register as the last one!
         */
        writeI2cRocksetta(devAddr, 0x35, 0xf);// SW1 to 3.0V (SW1_VOLT)

I think the last line should be 0x35, 0x3f but not sure. Also I feel like some of these values are probably incorrect for the latest PortentaH7 bootloader.

I bricked 2 Portenta just making this code. I have restored one of them. If an engineer thinks the code is the best we can do, I will make a video about it.

hpssjellis commented 1 year ago

Update:

Rumor's have it that the Segger jlink edu system can load code onto the Portenta but can't actually update the bootloader, so my next step is the ST-Link-V2 dongle. which has a large 10 pin male output, that does not plug into the 20 pin Breakout board of vision shields. I ordered a cheap conversion board.

This conversion board arrived
image and was completely useless. So I have now ordered this cable. Which might do what I need to connect the ST-LInk-V2 dongle to the Portenta Ethernet Vision shield which unlike the Breakout board or LoRa vision shield has the 10 pins avalable from the 20 pin connector.

image

In the mean time, does anyone know the exact HD connector pins that the 20 pin breakout board uses. I can find a few of them but really want to make sure I am fully correct. If I have all the pins then I can try connecting my st-link-v2 dongle to my HD dev board. I might even get a proper 20 pin st-link-v2 if that is a better arrangement.

This link looks helpful https://github.com/ardnew/portenta-tools and here is an image from it.

image

It has a few of the HD pins mentioned and I guess I can probably find the other pins, but then I need to find out which pins are the ones needed by the ST-LINKV2-dongle. The project continues.

Here is a breakout board image that just needs the HD connector pins

image

hpssjellis commented 1 year ago

So the 2nd cable I purchased that I thought would connect the st-link-v2-dongle to the ethernet vision shield actually had the wrong sized small connector.

lol-wrong

hpssjellis commented 1 year ago

So I got my portenta HD connector PCB connected. st-link-my-pcb

And then added a few more wires (SDA1, SCL1, GND) to connect another Portenta with the fixer app I made https://github.com/hpssjellis/my-examples-for-the-arduino-portentaH7/blob/master/research/i2c-orange/a12-full-app-orange-led-fix.ino This image shows an Orange ELD of Hell about to be fixed (hopefully)

orange

I found out you need the external power for the Orange LED fix, but you don't need it for the ST-Link to cubeProgrammer.

stlink-my-pcb-connected

So, of my 8 messed up Portenta's with the Orange LED of Hell, 2 would not get fixed using my App, mainly the I2C connectivity would not work. 2 Got the Orange LED of Hell fixed and I installed the Portenta Bootloader with the st-link v2 dongle but they still have port connectivity issues and 4 were completely fixed.

results

Probably a fair analysis of the screwups done to the Portenta. Any minor bad connection causes an Orange LED of Hell but no real physical damage is done to the board. If a student makes a really bad connection and damages the board then it can not be fixed. Probably a good reason not to use the Portenta in the classroom. I now use a very cheap board for most of my teaching and only the Portenta when students need the WiFi or more pins than normal.

I think we can close this issue now.

.

@sebromero @per1234 @mbanzi

By the way, I will try to talk to Arduino about my PCB. It seems I can not send it directly to some people in some countries as customs seizes it as a Hacker board. I do not want to get into the PCB board manufacturing business (I have no dreams of getting rich, that's why I became a teacher!), and since it has 4 x HD connectors to solder, which are not for the feint of heart, I am not sure how useful making the PCB Gerber files opensource would be. Hopefully Arduino has some kind of a solution.

bsodmike commented 7 months ago

Hey @hpssjellis just bricked mine, going to contact support.

hpssjellis commented 7 months ago

@bsodmike Good luck. This is one of my main issues with the Portenta. I have even thought I unbricked a few and then they went back to being bricked.

One thing Arduino ciuld do is sell the Portenta with headers pre soldered, not sure how many of my bad boards were from my bad soldering. I now have a soldering microscope that helps make every solder perfect.

bsodmike commented 7 months ago

Yeah that's essential. I picked up the cheapest LCD scope of Amazon and use that. My eyesight now isn't like it was during my Uni days and need it.

Ragarnoy commented 4 months ago

hey, really interesting thread, have you ever had a case of not getting any acks during the I2C communication ? I'm using a nucleo stm32l433rc as an i2c master and i'm running this code

async fn main(_spawner: Spawner) {
    let mut config = Config::default();
    config.rcc.sys = Sysclk::PLL1_R;
    config.rcc.hsi = true;
    config.rcc.pll = Some(Pll {
        source: PllSource::HSI,
        prediv: PllPreDiv::DIV1,
        mul: PllMul::MUL10,
        divp: None,
        divq: None,
        divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2)
    });
    let p = embassy_stm32::init(config);

    // Initialize I2C with corrected clock speed for 1 MHz
    let i2c_conf = i2c::Config::default();
    let i2c = I2c::new_blocking(p.I2C1, p.PB8, p.PB7, Hertz(1_000_000), i2c_conf);
    let mut i2c = BlockingAsync::new(i2c);

    const CHIP_ID_EXPECTED: u8 = 0x7C;
    const START_ADDRESS: u8 = 0x08; // Starting I2C address to scan
    const END_ADDRESS: u8 = 0x70;   // Ending I2C address to scan

    let mut found_address: Option<u8> = None;
    let mut chip_id = [0u8; 1];

    // Scan through the range of addresses
    while found_address.is_none() {
        for address in START_ADDRESS..=END_ADDRESS {
            match i2c.read(address, &mut chip_id).await {
                Ok(_) if chip_id[0] == CHIP_ID_EXPECTED => {
                    info!("Found PMIC at address: 0x{:02X}, ChipID: 0x{:02X}", address, chip_id[0]);
                    found_address = Some(address);
                    break;
                },
                Ok(_) => {
                    warn!("Incorrect ChipID at address: 0x{:02X}", address);
                },
                Err(e) => {
                    warn!("Communication error at address: 0x{:02X}: {:?}", address, Debug2Format(&e));
                }
            }
        }
    }

    // Check if a correct device was found and proceed
    if let Some(address) = found_address {
        // PMIC register writes to fix the power configuration
        let reg1: u8 = 0x9C;
        let val1: u8 = 0x80;
        let reg2: u8 = 0x9E;
        let val2: u8 = 0x20;

        // Writing to PMIC registers
        i2c.write(address, &[reg1, val1]).await.expect("Failed to write reg1");
        i2c.write(address, &[reg2, val2]).await.expect("Failed to write reg2");

        info!("PMIC configuration updated successfully at address: 0x{:02X}", address);
    } else {
        error!("Failed to locate a PMIC with the correct ChipID.");
    }
}

but all I'm getting are NACKs...

bsodmike commented 4 months ago

@Ragarnoy I'm away till 25th but if no one comments by then, I'll see if I can test the above on my H7. I need to get I2c working next.

BTW How did you manage to get DMA/BDMA on your chip? I haven't had time to test the memory mapping for the H7 yet.