Incorrect register setting for TWIM 400kHz frequency

Olfox recently raised a concern with the 400kHz frequency setting for the TWIM peripheral, which I confirm is incorrect in the SDK (17) and nRF52832 datasheet (v1.7); I attempted to write code to determine correct settings but there appears to be a maximum divisor above which the frequency falls rather than increases.

The quoted value for 400kHz is 0x06400000, however this does not work at anything like the correct rate. 0x05F00000 appears to be the largest value that is meaningful (on the v2 part I have to hand) and generates nearly the required 400kHz.

The discussion is here gpio-to-1-7v-after-enabling-twi though as that discussion is now locked I am posting this new thread. My updated calculations are here:

#define MAGIC_SCALE_FACTOR 32
#define MAGIC_SYSTEM_CLOCK 16000000ULL; // Typically 16MHz for TWI/TWIM/SPI/SPIM
#define MAGIC_INACTIVE_BIT_MASK      0xFFFF0000UL
#define MAGIC_INACTIVE_ROUNDING_BIT      0x8000UL
#define MAGIC_MAX_REGISTER_VALUE     0x7FFFF000UL
STATIC_ASSERT(((~MAGIC_INACTIVE_BIT_MASK+1)>>1) == MAGIC_INACTIVE_ROUNDING_BIT, "MAGIC_INACTIVE_BIT_MASK incorrect MAGIC_INACTIVE_ROUNDING_BIT");

//  --------Calculated-------------------  --------Documentation--------
//  Required Register      Actual   Error  Register    Required   Actual
//  ======== =========== ======== =======  =========== ======== ========
//   100000, 0x019A0000,  100097, +0.097%  0x01980000,  100000,  100000,
//   200000, 0x03330000,  199951, -0.024%           -,       -,       -,
//   250000, 0x04000000,  250000, +0.000%  0x04000000,  250000,  250000,
//   400000, 0x06660000,  399902, -0.024%  0x06400000,  400000,  400000,
//   400000, 0x05FF0000,  374755, -6.311%  0x06400000,  400000,  400000,

// Note 0x06660000 entry does not work as expected above 0x05F00000

  CalculatedRegisterValue = (uint32_t)((((uint64_t)RequiredBaudRate << MagicScaler) / SystemClock) + MAGIC_INACTIVE_ROUNDING_BIT) & MAGIC_INACTIVE_BIT_MASK;

Thanks to Olfox for instigating this investigation; we would appreciate a review by Nordic.

Parents
  • Hi,

    I only recommend to use the frequency values listed in the datasheet, since those are the ones that have been tested and qualified in specific.
    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/twim.html#register.FREQUENCY 

    Note however, that there is an I2C timing spec violation for 400kHz, so you should configure 390kHz instead:
    https://infocenter.nordicsemi.com/topic/errata_nRF52832_Rev3/ERR/nRF52832/Rev3/latest/anomaly_832_219.html#anomaly_832_219 

    Ideally for most accurate I2C (twi) clock you should have an accurate HFCLK, so for testing you can start the external 32MHz before configure and use twi, if you are not using the softdevice starting the external 32MHz can be done by:

        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART = 1;
        while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
          ;
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;

    However if you are not starting the external 32MHz it should run off the internal RC oscillator, which should not differ by more than max <6% if i remember correctly, but in your case I get an impression it's considerably more. 

    I do not understand why you differ significantly from the stated frequency values, I suggest you run for instance the default twi scanner examples from the nRF5 SDK for comparison. In general make sure the peripheral is disabled (and not have been configured by other peripheral instance/driver prior), and make sure for instance to configure twi before you enable twi.

    So to wrap up, I recommend you find out why the recommended values don't work as expected, instead of trying to find some values that seemingly work.

    Best regards.
    Kenneth

  • I repeated the test with bare metal drivers and crystal enabled and find the official figures quoted do indeed work with the proviso of the errata you refer to, so there is some other interaction as you suggest affecting the frequency in our design. This probably implies a bug in our code.

    The figures I calculate I believe are correct, which differ slightly from the documentation. Does it matter? Well, not really as the difference is very small.

    //  --------Calculated-------------------  Documentation
    //  Required Register      Actual   Error  Register
    //  ======== =========== ======== =======  ===========
    //   100000, 0x019A0000,  100097, +0.097%  0x01980000,
    //   200000, 0x03330000,  199951, -0.024%           -,
    //   250000, 0x04000000,  250000, +0.000%  0x04000000,
    //   390000, 0x063D0000,  389892, -0.027%  0x06200000,
    //   400000, 0x06660000,  399902, -0.024%  0x06400000,
    

Reply
  • I repeated the test with bare metal drivers and crystal enabled and find the official figures quoted do indeed work with the proviso of the errata you refer to, so there is some other interaction as you suggest affecting the frequency in our design. This probably implies a bug in our code.

    The figures I calculate I believe are correct, which differ slightly from the documentation. Does it matter? Well, not really as the difference is very small.

    //  --------Calculated-------------------  Documentation
    //  Required Register      Actual   Error  Register
    //  ======== =========== ======== =======  ===========
    //   100000, 0x019A0000,  100097, +0.097%  0x01980000,
    //   200000, 0x03330000,  199951, -0.024%           -,
    //   250000, 0x04000000,  250000, +0.000%  0x04000000,
    //   390000, 0x063D0000,  389892, -0.027%  0x06200000,
    //   400000, 0x06660000,  399902, -0.024%  0x06400000,
    

Children
No Data
Related