Cannot set the speed of I2C bus on Arduino Giga R1

Wire.setClock(100000);
Wire.setClock(400000);
Wire.setClock(1000000);

The above lines compile but do not alter the I2C bus speed. Any other value gives the "red blinking light"

The same sketch on ESP32 works great - I had it set to 1Mhz
Can anyone help please...

I'm not a Giga user. Looking at the core, the question arises if you issue Wire.setClock() after Wire.begin() or before?

I set it after Wire.begin();

OK, in that case I have no idea. Sorry.

(no GIGA R1 user either)

The wire.cpp (GIGA R1 version 4.4.1) has the function.

void arduino::MbedI2C::setClock(uint32_t freq) {
	if (master != NULL) {
		master->frequency(freq);
	}
#ifdef DEVICE_I2CSLAVE
	if (slave != NULL) {
		slave->frequency(freq);
	}
#endif
}

but it will fail if master is NULL.

Master is created in begin() as a new mbed::I2C object

void arduino::MbedI2C::begin() {
	end();
	master = new mbed::I2C(_sda, _scl);
}

void arduino::MbedI2C::begin(uint8_t slaveAddr) {
#ifdef DEVICE_I2CSLAVE
	end();
	slave = new mbed::I2CSlave((PinName)_sda, (PinName)_scl);
	slave->address(slaveAddr << 1);
	slave_th = new rtos::Thread(osPriorityNormal, 2048, nullptr, "I2CSlave");
	slave_th->start(mbed::callback(this, &arduino::MbedI2C::receiveThd));
#endif
}

Now try to find that mbed::I2C object

(update) searched for 15 minutes in the files but no clue why it should not work.
The only thing I would try is to add a delay(10) or so between Wire.begin() and the Wire.setClock call so all things under the hood get time to initialize.

Thank you. I have been away to Botswana for a week so was not able to try the above. Now that I did, I still cannot get it going. I am just not clever enough :grin:
Do anyone know where else I can get an answer/work around??

I am using the GIGA R1 I2C but I'm using the mbed class directly (so I can take advantage of the async transfer method that uses a callback).

mbed::I2C i2c_1(PIN_SDA, PIN_SCL);
...
i2c_1.frequency(I2C_CLOK_RATE);

Using the mbed class directly the frequency() method definitely does set it correctly. Don't know why it's not working with Wire as I don't use it.
How are you checking to see if the change is/isn't taking effect?

p.s. double-check you are using the correct Wire instance, there are three of them (Wire, Wire1, Wire2)

I am using Wire (pin20 SDA, pin 21 SCL). And I am getting the correct values from Adafruit_FXOS8700 and Adafruit_FXAS21002C. The fastest I can read the values is 455 readings/second. That is the same when reading it on the ESP32 at 400000. When I change it on the ESP32 to 1000000 the readings more than double. Nothing change on the Giga R1 when changing the i2c speed. And any other value except for 100, 400 and 1000 give me the 'red blinking light'.
I am not an exceptionally proficient programmer - just just better than a newbie - can you please explain how to use the mbed class??

The mbed i2c for the STM only supports those three frequencies - as you've seen it throws an exception if anything else is specified (see line 725)

In order to use the mbed APIs directly I've written my own classes. The adafruit libs are coded to use wire so likely not a quick task to rework them. I did notice that the adafruit I2C code does its own wire.setClock(). I wonder if that's having an effect but then can't see why ESP is working.

I want to use the Giga R1 as the ESP32 do not have enough io's. Another problem I ran into is running the two cores on the Giga. The M4 core must just read the sensors into variables and the M7 core must process the data. On the ESP32 it was easy, one core read and update variables, the other core read and process the data. The sensors are read at 1000 readings/second. If the processing core access the variable while the sensor core is writing to it the data can be out 1ms at most. Which is not a problem. I cannot get this working on the Giga as M4 writes to memory but M7 reads from the memory buffer as I understand it. Another problem I must try and solve once I can get the I2C speed up to 1000000hz.

Might be able to help with that one. I use D3 SRAM4 (0x38000000 - 0x3800FFFF) to pass data between cores. To disable the cache for D3 on the M7 I use:

  MPU_Region_InitTypeDef MPU_InitStruct;

  HAL_MPU_Disable();

  MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
  MPU_InitStruct.BaseAddress      = D3_SRAM_BASE;
  MPU_InitStruct.Size             = MPU_REGION_SIZE_64KB;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
  MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsShareable      = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.Number           = MPU_REGION_NUMBER15;
  MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
  MPU_InitStruct.SubRegionDisable = 0x00;
  MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
  
  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

Thank you. I will try that.
Will ask Gemini how to use D3 SRAM4 :laughing:

I use a struct and a pointer declared in both cores. I have two-way transfers so the struct is a little more complex than you'd need for one-way.

// SRAM4 (Domain 3) max 64,511 Bytes (0x3800FFFF minus 0x38000400)

struct sharedLogData {
      char logName[LOG_NAME_LEN+1];
   uint8_t CMD;
  uint32_t a_nextByte;
  uint32_t b_nextByte;
  uint32_t chunkSize;
      char a_buffer[LOG_A_BUFF_SIZE];
      char b_buffer[LOG_B_BUFF_SIZE];
};

sharedLogData * const sharedLogDataPtr = (struct sharedLogData *)0x38000400;

Do I need to put the code in post#11 in M7 and M4 sketch?

Do you know if the write to the shared memory is atomic for 8, 16 and 32 bit values?

Just M7 as M4 doesn't cache.

As I understand it, yes, providing it's a single operation. However, If, for example, you were incrementing a variable (i++) then that would generate a read, the addition and then a write which wouldn't be atomic. Happy to be corrected as I'm no expert.

Regarding Post#11
Do I need extra includes?
Does this code go into Setup()?
And thank you for your help

Nope

I have it in setup before booting the M4

No problem

The code compile. But unfortunately not working,

SCB_InvalidateDCache_by_Addr((uint32_t*)(AHB_SRAM3_ADDR), 64);

This is working, M4 to M7, but not M7 to M4 (I need to send one variable to M4 fromM7)

But for my use case it is impractical to Invalidate the cache before each and every read. I hope I can get your solution up and running.

I use the RPC library and RPC.begin() to start the M4 core. Maybe the RPC l;ibrary is the problem?