SparkFun Forums 

Where electronics enthusiasts find answers.

Everything with the AmbiqSuite SDK tools and software are welcome here.
By SidPrice
#218058
While I am an experienced programmer I am struggling to wrap my head around the Ambiq SDK, it appears to lack any high-level conceptual description of how their API is structured. Yes, there are lots of example projects in the SDK, however, I have failed to find a simple I2C master example. I am using the Apollo3 EVB.

I would really appreciate pointers to an example for implementing an I2C master that operates with an external slave device. Failing that, if someone knows of a good getting started with the Ambiq SDK that presents the API structure and usage that would certainly help.

Sid
User avatar
By liquid.soulder
#218184
Hi Sid

We have found the same thing. For me the best way to utilize the SDK and HAL layer is to read the header files. Of course if we all had to do that it would take a lot of duplicated effort. So I'll point you to an example that could maybe help.

First of all - I recommend using SparkFun's mirror of the SDK. It uses version control so it is possible to track issues and possibly even use patches for a few bugs in the SDK. It is available at the following link and the README.md file would be a good start.
https://github.com/sparkfun/AmbiqSuiteSDK

The mirror of the SDK contains a reference to the SparkFun BSPs repository - which contains board definitions for SF boards and also examples. Again, the README.md file is a good place to start - it will tell you how to build examples.
https://github.com/sparkfun/SparkFun_Ap ... Suite_BSPs

Within the BSPs repo there is an I2C example. It is super basic but it could be a good starting point
https://github.com/sparkfun/SparkFun_Ap ... amples/i2c

Hope that helps, shout if there are any questions. If you find bugs please submit an issue on GitHub.

Best of luck!
By SidPrice
#218190
Hi and many thanks for taking the time to respond.

I have made a little progress since I posted my appeal for an example. And, as you suggested, reading the code and the header files of the Apollo SDK seems to be the only way to get any progress, what a PITA.

My I2C code is reading from my device, however, my write function is not working. I notice in the example you linked to in the SparkFun mirror, the "offset" entry in the transaction structure is not used. In my reading function I placed the "command" to the I2C device in the "offset" entry and set the instruction length to "1". That appears not to work with the TX operation.

I will give the approach in the linked example a try and see if that works.

Again, thanks,
Sid
By SidPrice
#218191
I updated my write function to not use the "offset" parameter, I now pass the "command" in the buffer. Thanks so much for that pointer.
Sid
User avatar
By Menaures
#219122
Hi Sid,

I am working on a project including the Artemis Nano and also struggling to fully understand the am_hal_iom_nonblocking_transfer function. I simply need to read sensor values via I2C. I assume you were using this function to get the I2C communication to work. Would you be so kind to explain how you have used the offset to specify the sub-adress of the register you were trying to read?
What I have tried so far is to send two bytes with the first one containing the 7-bit slave address plus the write bit and the second byte being the sub-address of the register containing the sensor measurements. In a second function call I have set the read/write bit to read and the direction to read as well, expecting the sensor value to get stored in the RxBuffer. Unfortunately that did not work.
I tried to follow along the datasheet for the ST LSM6DSOX, which can be found here for reference: https://www.st.com/en/mems-and-sensors/lsm6dsox.html.
If you could provide me with a simply read and write example, that would be really highly appreciated.

Menaures
By SidPrice
#219151
Menaures,

This is the read method of my application:
Code: Select all
//*****************************************************************************
//
// Read "size" data into "pBuf" to the usfsmax
//
//  The "reg" parameter is the address of the register to be read.
//
//*****************************************************************************
void usfsmax_read(uint32_t reg, uint32_t *pBuf, uint32_t size)
{
    am_hal_iom_transfer_t Transaction;

    Transaction.ui32InstrLen = 1; // registers are single byte
    Transaction.ui32Instr = reg;
    Transaction.eDirection = AM_HAL_IOM_RX;
    Transaction.ui32NumBytes = size;
    Transaction.pui32RxBuffer = pBuf;
    Transaction.bContinue = false;
    Transaction.ui8RepeatCount = 0;
    Transaction.ui32PauseCondition = 0;
    Transaction.ui32StatusSetClr = 0;
    Transaction.uPeerInfo.ui32I2CDevAddr = USFSMAX_I2C_ADDR;
    am_hal_iom_blocking_transfer(g_I2C1Handle, &Transaction);
}
I hope this helps,
Sid
User avatar
By Menaures
#219165
Hi Sid,

thanks for your help. This has already been helpful.
Although, for the puzzle to be complete, it might be useful to see the initialization of the g_I2C1Handle, because I don't understand the role of the g_I2C1Handle.pNBTxnBuf.
Two further questions concering the device and register addresses just to make sure this isn't the cause of the issue. Is the device address USFSMAX_I2C_ADDR the 7-bit or the 8-bit address with the read bit set?
Most registers have 8 or 16-bit addresses, but the instruction Transaction.ui32Instr is stored in a uint32_t, which makes me wonder whether the remaining 24-bit for a 8-bit address should be appended as a prefix or a suffix. I assume it is a prefix so a hex address 0x0F would expand to a binary 0000 0000 0000 0000 0000 0000 0000 1111, am I right?

Thanks,
Menaures
By SidPrice
#219174
First you need to create a configuration for the I2C:
Code: Select all
static am_hal_iom_config_t g_sIOMI2cConfig =
    {
        .eInterfaceMode = AM_HAL_IOM_I2C_MODE,
        .ui32ClockFreq = AM_HAL_IOM_100KHZ,
};
Then you use this to configure the IOM:
Code: Select all
    am_hal_iom_configure(g_I2C1Handle, &g_sIOMI2cConfig);

    am_bsp_iom_pins_enable(iomModule, AM_HAL_IOM_I2C_MODE);
Is the device address USFSMAX_I2C_ADDR ...
It is the address of the I2C device you are trying to connect with, the read/write bit is NOT included in this address.

All the I2C peripheral registers are 32-bit, including the data fifo. You need to read the datasheet to understand how this works, it would take too long for me to cover that subject in this forum.

Good luck
User avatar
By Menaures
#219177
Thanks again,
I got the reading function working by now and the configuration for the I2C is basically identical to yours.
I just realized it doesn't matter how many address bits are being used due to the typecasting to a uint32_t. :roll:
Meanwhile I am pretty familiar with the datasheet, although it has rather led to confusion, because the am_hal_iom_blocking_transfer function is way more abstract than the low level description of the I2C communication in the datasheet.
There is just one more issue with my write function. Thus I would really appreciate if you could share this precious piece of code as well, which should finally allow me to make use of the full functionality of this amazing IMU.

One could consider to add an I2C example with your read and write functions to the boards_sfe repository, so that others have it easier to get started with I2C in the Ambiq Suite SDK...

with kind regards,
Menaures
User avatar
By Menaures
#219199
SidPrice wrote: Wed Aug 19, 2020 10:43 am I updated my write function to not use the "offset" parameter, I now pass the "command" in the buffer. Thanks so much for that pointer.
Sid
That's what I have tried as well. For me it didn't work, but the same approach as with the read function did the job. So the write function is exactly the same as the read function with Rx replaced by Tx in the direction and the buffer.

Thought I would add this for the sake of completeness.
By SidPrice
#219202
Here is my write code:
Code: Select all
//*****************************************************************************
//
//  Write "size" data from "pBuf"
//
//  Note:
//      The address to be written to must be included in the passed buffer and
//      the size parameter.
//
//*****************************************************************************
void usfsmax_write(uint32_t *pBuf, uint32_t size)
{
    am_hal_iom_transfer_t Transaction;

    Transaction.ui32InstrLen = 0;
    Transaction.ui32Instr = 0;
    Transaction.eDirection = AM_HAL_IOM_TX;
    Transaction.ui32NumBytes = size;
    Transaction.pui32TxBuffer = pBuf;
    Transaction.bContinue = false;
    Transaction.ui8RepeatCount = 0;
    Transaction.ui32PauseCondition = 0;
    Transaction.ui32StatusSetClr = 0;
    Transaction.uPeerInfo.ui32I2CDevAddr = USFSMAX_I2C_ADDR;
    am_hal_iom_blocking_transfer(g_I2C1Handle, &Transaction);
}
User avatar
By Oxcart
#219209
There are working examples of both an I2C (servo driver) and SPI (imu) device here:

https://github.com/0xcart/artemis

Refer to the README to understand how to use/setup IOM.
See artemis_i2c.c and artemis_spi.c for respective send/receive/transfer functions.
See artemis_pca9685_initialize() in artemis_pca9685.c for how to setup the I2C device.
See artemis_icm20649_initialize() in artemis_icm20649.c for how to setup the SPI device.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

long long title how many chars? lets see 123 ok more? yes 60

We have created lots of YouTube videos just so you can achieve [...]

Another post test yes yes yes or no, maybe ni? :-/

The best flat phpBB theme around. Period. Fine craftmanship and [...]

Do you need a super MOD? Well here it is. chew on this

All you need is right here. Content tag, SEO, listing, Pizza and spaghetti [...]

Lasagna on me this time ok? I got plenty of cash

this should be fantastic. but what about links,images, bbcodes etc etc? [...]