Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years, 6 months ago.
ST32L476RG and I2C Transfer support
Does the ST STM32L476RG have support in the mbed OS for I2C.transfer(...)? It is in the documentation and can compile, but the peripheral pins are not affected and the callback is never called. A simple read/write works.
1 Answer
6 years, 6 months ago.
Hello Stephen,
I2C transfer is a function of the Mbed OS system. Therefore, it should be supported for all Mbed enable MCU. Can you post your code so that I can try to recreate the problem and maybe figure out what is wrong?
Please let me know if you have any questions!
- Peter, team Mbed
If this solved your question, please make sure to click the "Thanks" link below!
Thanks for the help. I've stripped down the code and posted below. I can see the first write transaction on my logic analyzer - though I am receiving a NACK on the write. However, regardless of the ACK or NACK I should be hitting my callback, but this is never reached. My code gets stuck on the flag that is never cleared in the callback. (Note: In other implementations using FreeRTOS I've use thread safe methods for this busy flag, but I'm pretty sure in this case a global variable will work. I have tried making this flag static with the same result.)
<<code>
- include "mbed.h"
/* I2C */
- define SDA1 PB_7 /*<< */
- define SCL1 PB_6 /*<< */
- define PERIPHERAL_BUSY -1
- define TRANSFER_STARTED 0
- define I2C_RETRY_DELAY_MS 1 I2C i2c1( SDA1 , SCL1 );
/* MLX90614 */
- define mlx90614_i2c i2c1
- define MLX90614_TA_RAM_ADDRESS 0x06
- define MLX90614_TOBJ1_RAM_ADDRESS 0x07
- define MLX90614_I2C_ADDRESS 0xB4 8-bit adressing
- define mlx90614_conversion( x ) ((((((x[1]&0x007f)<<8)+x[0])*0.02)-0.01)-273 ) see data sheet for counts to degrees C conversion values
bool mlx90614_i2c_busy;
void mlx90614_i2c_callback( int argument ){ mlx90614_i2c_busy = false; } void mlx90614_i2c_transfer( const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length ){
while( mlx90614_i2c_busy ) {}; mlx90614_i2c_busy = true; while( TRANSFER_STARTED != mlx90614_i2c.transfer( MLX90614_I2C_ADDRESS, tx_buffer, tx_length, rx_buffer, rx_length, mlx90614_i2c_callback, I2C_EVENT_TRANSFER_COMPLETE, false ) ) { wait_ms( I2C_RETRY_DELAY_MS ); }; while( mlx90614_i2c_busy ) {}; } void mlx90614_init( void ){ mlx90614_i2c_busy = false; } float get_Temperature( int address ){ char tx[1],rx[3]; float temperature;
tx[0] = address; mlx90614_i2c_transfer( tx, 1, rx, 3 ); temperature = mlx90614_conversion( rx ); return temperature; } float mlx90614_getTemperatureAmbient( void ){ return get_Temperature( MLX90614_TA_RAM_ADDRESS ); }
int main( void ){
mlx90614_init();
while( true ){ float f = mlx90614_getTemperatureAmbient(); wait( 0.5 ); }
}
<</code>
posted by 19 Jun 2018Updated comment above. Also, I'm finding that any call to wait(...) gets hungup in "mbed_wait_api_rtos.cpp" on line 48. It seems that the call to ricker_read(ticker) on line 38 always returns 0. I'm not sure why these timers never get started. Thanks!
posted by 19 Jun 2018Hi Stephen, I had looked at your code and tested it using a similar sensor. It is seem to be working on my board. How are you debugging it? Can you try putting a break point mlx90614_i2c_callback function and run the code to see if the that function was ever call after the transfer function is complete?
- Peter, team Mbed
posted by 20 Jun 2018Peter, thanks again.
I'm using a Nucleo board and the St-Link Debugger through Keil. I've set a breakpoint at that callback, but it never gets hit. Any time I call any variation of wait(...) I get hung up as well. I set up the project by doing a copy/paste of a project created with the CLI specific to this IDE and target. It seems like I may be missing something in my setup file. I've added it below. It's a little silly that this is getting hung up. It's a pretty straightforward function. I have that feeling it's something simple that I'm overlooking.
Note: looks like I'm character limited in a response. I'll post the file in the original question above.
posted by 20 Jun 2018Hi Stephen, Can you try exporting the project to Keil instead of copy/paste? You might have missed config when you just copy/paste the code. If you go to your Online Mbed Compiler and click on your project folder, on the very right hand column which called Project Details, there should be an Export button. Click on that and it should open up another window that allowed you to choose your IDE export config.
posted by 20 Jun 2018@Peter
I just copied all that code into the online compiler, built and loaded the file and it is working. I exported that to my IDE and debugged the program. It is working and hitting a breakpoint in the callback. There has to be something wrong with the configuration of my original project, but I'm not sure what it is. Any suggestions on where to look?
Thanks, Stephen
posted by 20 Jun 2018@Peter Sorry, when I said "copy/paste", I do that from Windows explorer. I start with a starter project that I have setup the way I like it, then copy that and customize it into a new project. I do this because rather than use the mbed library within my project, I place it one directory above, create an mbed.lib and then all my projects share the same mbed library (much more lightweight in storage and compilation time). The pain is setting up the project's include directories each time. That's why I use a template project. I also have to use the correct target's startup file.
Is there an issue with setting up a project this way? I've done this with other APIs, but I know that the online compiler and the CLI's export function sets up a project specific to my target and IDE. Am I missing something with my method?
posted by 20 Jun 2018Hi Stephen,
It seems that your problem is how to compile a static Mbed OS library for all your project. The instruction on how to do that is here: https://github.com/ARMmbed/mbed-cli#compiling-static-libraries
If you run into any problem then you can reference these previous post:
- https://os.mbed.com/questions/76149/linking-mbed-libs-in-one-directory-to-mu/
- https://os.mbed.com/questions/77558/How-to-generate-mbed-os-static-library-a/
- https://os.mbed.com/forum/mbed/topic/28056/?page=1#comment-53941
Please let me know if you have any questions!
- Peter, team Mbed
If this solved your question, please make sure to click the "Thanks" link below!
posted by 20 Jun 2018@Peter
Thanks for that information on compiling static libraries. It seems that this may be where my issue lies - once I move to a static library the breakpoint in the callback never get hit. Will you please try to replicate my setup and see if you have insight as to what the problem might be? I'll detail it below:
1) Copy main.cpp from above in the online compiler, compile and load onto device to confirm code is valid (STM32L476RG). 2) Export project into Keil uVision5, compile, set breakpoint in callback, debug and confirm breakpoint is hit. 3) In Keil's project options -> Ouput, select Create Library to generate a .lib file containing mbed-os library local to project (may choose to first remove main.cpp from project then replace after compilation). 4) Remove "mbed-os" group from project. 5) Add a new group to the project and add the newly created .lib and the correct startup file (startup_stm32l476xx.s) found in the local mbed-os directory. 6) Compile (don't forget to change project options -> Output back to Create Executable) to confirm compilation and linking are valid. 7) Debug project and see if breakpoint during callback is hit.
This should produce a project that is using the same content as before, only in a .lib rather than the source files. But when I follow this procedure my code will run, but has an issue with the callback. With this setup I am not using a localized library, I am just converted the one imported from the online compiler to a static library. It's possible there is an issue with how Keil generates the static lib and I'll follow the link you sent above to see if that changes anything.
On an interesting note, I have been using centralized static libraries for this same project and am using a SPI callback without any issue. It was only when I added I2C operations and used the I2C callback that I ran into the issue.
Thanks, Stephen
posted by 21 Jun 2018Hi Stephen,
I had talked to our MBed developers and they said it is not possible to create a static Mbed OS library. This is because inside Mbed OS library, there are weak-symbolic link that allowed the Mbed OS to overwrite C standard library function like malloc and dealloc. This is to make these functions thread safe, a requirement in an RTOS system. Therefore, without the weak-symbolic link, the transfer function might possible be using the standard C library and running into a race condition somewhere. Mbed OS 2 used to support static library but Mbed OS 2 is not a RTOS system. That why, Mbed OS 5 required you to have a Mbed OS folder inside each of your project.
Peter, team Mbed
posted by 21 Jun 2018
Sorry! Below should be the properly formatted code. Also, compiling the with Keil ARMCC latest update of mbed OS as a .lib, using "startup_stm32l476xx.s"
mbed_config.h