Reply
Posts: 91
Registered: ‎11-07-2016
Accepted Solution

I do have a problem setting registers to my device over I2C...

I thought I had my accelerometer initialization over I2C working but in the process of trying to get interrupts to work I discovered that the accelerometer was not generating them. So I started debugging and discovered that I am not properly configuring the device. I do know that I can read registers on the device but apparently I'm not setting them properly. This is an artifact of my lack of understanding how the SMBus library works (and I have now read the header file several times and thought I discovered my issue but had not) and that almost all of my I2C programming has been done on Arduinos using the Wire library - which seems to "do the right thing" with respect to setting registers on this and other devices I've used.

 

So here's some detail. 

LIS2DH accelerometer data sheet

 

The device is accessed through a set of registers. Some are readonly some are read-write. I know I am communicating with the device because I can access the "WHO_AM_I" byte in that register (it's 0x33). 

 

So reading is working. The issue is in setting the register. For this thread, I'll focus on a very simple case and I've refactored my program to concentrate on this case to make it easy and quicker to test until I figure this out. The case is setting and reading CTRL_REG1 (0x20) described in section 7.6 on page 33. 

 

The default value for the contents of this register are 0x7 - meaning that the X, Y and Z axes are enabled. I want to modify that to only enable the Z axis. 

 

To refresh, I am starting with the SMBus_Lib_Buffered_Master_Multiple_Byte example. I've modified main() to focus on getting this to work. To start, I read the CTRL_REG1 to make sure I'm reading the device and getting the default value:

 

    	transferInProgress = true;

    	SMB_DATA_OUT[0] = CTRL_REG1;
        SMB0_transfer(IIS2DH_ADDRESS<<1, SMB_DATA_OUT, SMB_DATA_IN, 1, 1);

        // Wait until transfer complete callback is called
        while (transferInProgress);

--> ctrlReg = SMB_DATA_IN[0];

 

Breaking at the indicated line, ctrlReg contains 0x7 - the default value. So that is working. Now I want to set the CTRL_REG1 to 0x4 which sets Z enable and clears X and Y enable.

 

I implemented a setRegister() as:

 

 

//-----------------------------------------------------------------------------
// Set accelerometer register
//-----------------------------------------------------------------------------
void setRegister(uint8_t reg, uint8_t value)
{
	// Error counter
	numErrors = 0;

	transferInProgress = true;

        // Start write/read transfer
        // Set register we want to read (no returned data)
	SMB_DATA_OUT[0] = reg;
        SMB0_transfer(IIS2DH_ADDRESS<<1, SMB_DATA_OUT, SMB_DATA_IN, 1, 0);

	// Wait until transfer complete callback is called
	while(transferInProgress);

	transferInProgress = true;

	// Start write/read transfer
	// Set the register value (no returned data)
	SMB_DATA_OUT[0] = value;
	SMB0_transfer(IIS2DH_ADDRESS<<1, SMB_DATA_OUT, SMB_DATA_IN, 1, 0);

	// Wait until transfer complete callback is called
	while(transferInProgress);

	// Indicate that an error has occurred (LED no longer lit)
	if (numErrors > 0)
	{
		BSP_LED_G = BSP_LED_OFF;
	}
	else
	{
		BSP_LED_G = BSP_LED_ON;
	}
}

I call this as:

 

setRegister(CTRL_REG1, 0x4);

 

and then re-read the CTRIL_REG1 and discover it is still at the default value 0x7

 

After reading the SMB header file I *thought* my issue was that I had a "1" set for the number of bytes for SMB_DATA_IN when in fact I am not expecting a read, I'm trying to write. So I changed both of those to the "0" you see above but the write still fails.

 

In writing this and re-reading the SMB header and LIS2DH I2C operation on page 24, maybe I see the problem. Rather than writing two bytes stepwise, I should write 2 bytes in one step like this:

 //-----------------------------------------------------------------------------
// Set accelerometer register
//-----------------------------------------------------------------------------
void setRegister(uint8_t reg, uint8_t value)
{
	// Error counter
	numErrors = 0;

	transferInProgress = true;

        // Start write/read transfer
        // Set register we want to read (no returned data)
	SMB_DATA_OUT[0] = reg;
SMB_DATA_OUT[1] = value; SMB0_transfer(IIS2DH_ADDRESS<<1, SMB_DATA_OUT, SMB_DATA_IN, 2, 0); // Wait until transfer complete callback is called while(transferInProgress);
// Indicate that an error has occurred (LED no longer lit) if (numErrors > 0) { BSP_LED_G = BSP_LED_OFF; } else { BSP_LED_G = BSP_LED_ON; } }

So I just did a quick test and yes, that seems to be working! Sometimes stopping to describe what you are doing reveals a solution. I'll go ahead and complete this post so that maybe it will help someone else.

 

Now back to interrupts!

 

 

 

 

 

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

I was reading through your post and getting ready to suggest you do a single transfer with both the device register address and the new value in the payload as a 2 byte transfer, and found that you discovered that solution and included it in your post.  Great!  Let me know if you have further questions.

 

Regards,

Mitch

MCU Applications Engineer

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Thanks Mitch, right now my main issue is getting EXY INT 0 setup and working. Perhaps you read my other posts. The challenge is learning how to use the tools to accomplish what I need. The Configurator seems to do a lot of things but also generates code (an ISR that is continuously called) that does not run properly - and this is one of the stock example apps where the hwconf is obviously different than the generated code included in the example. 

 

Some users suggest that configuring everything in code is the best approach but that has the additional complexity of not appreciating all of the configuration nuances yet. All learning curve stuff but working in isolation (with this forum) is the only avenue I have. On the good news front, once I have this complete, the project will be Open Source so my code might be useful to others interfacing to sensors. A lot of sensors are available that integrate in the same way as this one: I2C communication with an interrupt generated to signal an event. An example project would probably be useful.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

I keep spending time on this but so far it's been unproductive. I would have thought it would be as simple as:

  1. DefaultMode Peripherals->Core: check External Interrupts and then edit INTO0 to be Active High on P0.7
  2. Select Core->Interrupts and set Enable External 0 Interrupt to Enabled
  3. save the configuration and regenerate code
  4. remove the SMBUS0_ISR stub (if left in, it is called continuously and the program hangs)

I then run the program in the debugger. I flash the blue LED in my main loop. I see the LED flashing. I then tap the accelerometer and the LED stays lit but I don't get a break in my ISR.

 

I have to stop execution but then when I try to debug again, the program seems to hang and I can't tell where. The only way to recover is to reset 1-3 above and then redo 1-4 above. Very odd. I did try unplugging the 2020A thinking that maybe the acclerometer's int was not cleared but that did not help.

 

I really don't understand how to use the Configurator if the above does not work and I don't know how to initialize manually so I am at a standstill except for poking at the keyboard like a monkey!

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

I am not completely sure but I think my problem is that the interrupts to service the SMB are conflicting/interfering with the EXT 0 interrupt. With the EXT 0 interrupt enabled and breakpoints disabled, stepping through my code, it seems to be hanging in the SMB wait "while(transferInProgress)". If I then enable breakpoints, the breakpoint in the INT0_ISR is immediately caught. So "while(transferInProgress)" to  read a byte from the accelerometer is happening, the INT0 ISR is being called - although there should not be an interrupt generated at this point. Stepping through the disassembly at this point the program is simply bouncing back and forth between "while(transferInProgress)" ( JB      3H, 2EEH) and the ISR.

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

I have a couple of questions about your setup, as I do not think I currently have enough information to debug this issue:

 

1) Please confirm: you are using the EFM8BB1 starter kit (STK)?

 

2) Is your INT0 interrupt configured as edge or level sensitive?  If it is edge sensitive, then the interrupt "flag" (IE0 in TCON) is cleared by hardware when the CPU vectors to the ISR.  If it is level sensitive, the IE0 pending flag will remain set as long as the interrupt signal is asserted, meaning that the ISR will run over and over again as long as the signal is asserted and there is no higher priority interrupt pending.

 

3) What is the polarity of your INT0 (i.e. active high or active low)?

 

4) What is the level of your interrupt signal coming from the sensor to your INT0 pin?

 

5) What are the priorities of your INT0, SMB0, and any other interrupts in your system?

 

Thank you for providing this additional information.  For more information on these settings, please consult the datasheet for the EFM8BB1 (or your device - let me know which device), especially the sections 6 (interrupts), 11.3.4 - INT0 and INT1, and 11.5 - INT0 and INT1 control registers.  Also, let me know if you have questions.

 

Regards,

Mitch

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

1) Yes, I have the 2020A BusyBee starter kit 

2) I want it set up as edge but I do not see that option in the Configurator. I have modified the generated code to select edge but can't tell if that makes any difference. I understand that edge autoclears the interrupt pending flag I have attempted to explicitly clear the flag in the ISR also but to no avail.

3) active high

4) 3v3 (I'm using P0.7)

5) Since I am using the Configurator and started with an example code, I don't know what the priorities are. I am not doing/setting anything explicitly for priority. Basically, I started with the SMBus_Lib_Buffered_Master_Multibyte and added my I2C initialization code. Got that working so I know the accelerometer is being initialized. I know that it is generating interrupts as I tested by polling its interrupt register AND I validated its interrupt 0 pin goes high on the oscilloscope. I am now trying to implement an interrupt handler to catch the event. I arbitrarily chose to use EXT INT 0 for this. The program will do nothing else except configure the accelerometer and wait for triggers. Well, once I have a trigger I'll need to output a signal on another pin but that should be easy (even for me).

 

Thank you. I have read through the EFM8BB1 data sheet multiple times focusing on I2C and interrupts. Like I said, I believe this is just learning curve stuff although I am a bit confused as to why the example code above fails if the configurator source is regenerated. 

 

Question: why doesn't it work like I would expect it to?! I'm only partly kidding. It does seem like the same code with no changes sometimes almost works (i.e. does not hang) but usually does not. I literally had something working to the point where I ran, initialized and got into a steady led blink in my main waiting. I then tapped the accelerometer and it triggered an interrupt that was caught by the generated EXT INT 0 handler - which was empty and had a breakpoint. But hung after disabling the breakpoint and the next time I attempted to run the same program in debugger it just hung outright and I've not been able to get back to that state - no edits or regeneration was done during this which is what really baffles me.

 

Posts: 8,078
Registered: ‎08-13-2003

Re: I do have a problem setting registers to my device over I2C...

I have read through the EFM8BB1 data sheet? do you mean 'reference manual?

erik
Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Yes, reference manual.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

An update...

 

I got things to a state where interrupt EXT 0 is *almost* working. I stepped through the generated InitDevice code and watched the Registers. I could see that the EXT INT 0 was being set up as I intended - edge trigger, pin P0.7, active high, enabled, all interrupts enabled, etc. This was helpful to watch. Then I ran with a breakpoint in the INT 0 ISR. My main loop flashed the LED as expected but when I tap the accelerometer, nothing happened. So, I pulled the interrupt wire from the accelerometer (connected to P0.7 on the Busy Bee board) and touched 3v3 pin on the expansion header. Nothing happened. So I touched it to ground on the expansion header, now I broke in the interrupt handler. So I changed my setup for the EXT INT 0 to active low. But I get the same result: break on touching ground, no break on touching 3v3. 

 

I also know that my accelerometer is generating an interrupt when I tap it - I have a little test app that polls the sensor and flashes the LED on a tap. The signal on the line is high when I tap (until I clear the interrupt via a register). So I know that is all working. What seems to be not working is active high for EXT INT 0 as described above. But at least this is progress! Am I misunderstanding something about configuring the EXT INT 0? 

 

In the Configurator DefaultMode Port I/O I select P0.7 and the settings are set as:

 

IOMode: Digital OpenDrain I/O

Latch: High

Mask Value: Ignored

Match Value: High

Skip: Skipped

Label: ""

 

I thought maybe I was using the wrong I/O mode so I changed that to Digital Push-Pull Output. Now the program does not recognize an interrupt when P0.7 is brought high or low. So I reverted back to OpenDrain and the program is still not recognizing high or low as before. No other changes were made except that one line change in a InitDevice.c. I cleaned and rebuilt and still nothing. This is the sort of thing that drives me bananas. 

 

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

I meant to suggest that you have a look at the example project "EFM8BB1 ExternalInterrupts," which you can open using Simplicity Studio:

 

ExtINT_example.png

 

Studying this example may help you figure out where you are going wrong with your project.  Please note that you have to set the edge/level sensitivity for external interrupts in the TIMER registers (TCON).  

 

Let me know if you are still having troubles.  Perhaps some screenshots, code snippets, or even an upload/attachment of your project would help, as it is hard to know for sure what is going on in your code.  Thank you.

 

Regards,

Mitch

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


mhackney wrote:

I am not completely sure but I think my problem is that the interrupts to service the SMB are conflicting/interfering with the EXT 0 interrupt. With the EXT 0 interrupt enabled and breakpoints disabled, stepping through my code, it seems to be hanging in the SMB wait "while(transferInProgress)". If I then enable breakpoints, the breakpoint in the INT0_ISR is immediately caught. So "while(transferInProgress)" to  read a byte from the accelerometer is happening, the INT0 ISR is being called - although there should not be an interrupt generated at this point. Stepping through the disassembly at this point the program is simply bouncing back and forth between "while(transferInProgress)" ( JB      3H, 2EEH) and the ISR.


Do you have edge interrupts set for  INT0

ie IT0  = 1  -> EDGE,  INT0 is edge triggered.

 

If you have level selected, it will re-enter INT0 vector right after RETI plus one other opcode.

 

A way to confirm you have correct  interrupt sense, is to run two buttons, and two leds.

One button is a simple test gate, to check the INT queue from the other button, and one led toggles inside the INT, to confirm, it is calling only once.

 

 

With a button in the active path, you may get bounce giving a few led toggles, but button outside the 2nd button gate, will queue in the TCON IE0 flag.

 

Notice the INT0 edge capture action, acts as a local queue/sticky flag, and you may then be able to just poll IE0, without needing an actual interrupt. 

 

A common oversight in MCU interrupt code, is to forget to clear the flag(s), or to have it triggered more often than you think. Both result in more frequent interrupts than the coder expected.

In a 8051 this should not totally hang, but it will execute only one other opcode per INT, which may result in very slow operation.

 

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...

[ Edited ]


I could see that the EXT INT 0 was being set up as I intended - edge trigger, pin P0.7, active high, enabled, all interrupts enabled, etc.

 


You really do not want 'active high', that is just a pain to work with, because it will re-enter.

Choose an edge instead.

 

 


So, I pulled the interrupt wire from the accelerometer (connected to P0.7 on the Busy Bee board) and touched 3v3 pin on the expansion header. Nothing happened. So I touched it to ground on the expansion header, now I broke in the interrupt handler. So I changed my setup for the EXT INT 0 to active low. But I get the same result: break on touching ground, no break on touching 3v3. 

The 8051 has a weak pullup, so touching a port pin to 3v3 will give no change of state.

Touching to GND, will give multiple edges.

ie What you observe here is totally expected behaviour.

 

 

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Thanks Mitch, yes I found that example a couple of days ago and have scrutinized it. That example works fine, my I2C example works fine but the union of the two is unholy!

 

However, somehow, someway I actually have it working now. I used Configurator exactly as I described above starting with a fresh copy of my known good I2C. I changed the IOMode to PUSH_PULL. After generating the source code I had to make 2 manual edits:

 

InitDevice.c: explicitly set TCON register bit 0 to enable edge triggering (why can't this be done in the Configurator?)

 

Interrupts.c: I had to remove the generated stub for the SMB interrupt. (why is this generated or why do I need to remove it? Seems Configurator should handle this correctly one way or the other.)

 

I also simply added a line of code to the INT0 ISR to set a global to true to let my main loop know an interrupt needs servicing.

 

This is working and I've started and stopped the program several times. I'm fearful that it could cease to work unexpectedly as I've encountered many times to get to this point. I've made a source copy so I have this new state to fallback to.

 

Meanwhile, I've sorted some of the issues I've had with the "program hanging". Every time I make a code change and recompile, I get some memory management error. See the attached. In the past, I simply clicked Debug to recompile and then run in the debugger. Turns out this memory issue was happening and I didn't notice/pay attention to it. Even though the program loaded in the debugger, when I execute it, I seemingly hang. Now, I recompile (hammer tool) and get this message. I then click Debug and it loads cleanly and runs fine. This happens 100% of the time. Any ideas on what's going on?

 

 

 

 

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

jmg, see my previous post, I have something working now. I have been using edge triggering but I need to set that manually in the generated Init code since there is no flag in the Configurator for it. 

 

I am getting clean predictable interrupts from the accelerometer configured as described. What's the issue with active high being a pain?

 

With edge triggering, the MCU clears it's interrupt. In the ISR I set a global to signal that an interrupt was caught. Then my main loop checks that signal and when it sees it, it does the additional processing I need and then clears the INT register in the accelerometer. This all works smoothly - at least for now.

 

 

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...

[ Edited ]


jmg, see my previous post, I have something working now. I have been using edge triggering but I need to set that manually in the generated Init code since there is no flag in the Configurator for it. 

 

 


Really ? If so, that probably should be fixed by SiLabs...

 


 

With edge triggering, the MCU clears it's interrupt. In the ISR I set a global to signal that an interrupt was caught. Then my main loop checks that signal and when it sees it, it does the additional processing I need and then clears the INT register in the accelerometer. This all works smoothly - at least for now.

 


Notice the ISR here is doing very little, aside from copying a flag.

Hence my suggestion to select Edge,and simply poll TCON_IE0 - no ISR needed.

 

 Of course, it is good learning to have the interrupt trigger.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

I could also poll the accelerometer over I2C directly. I think any of these approaches would work fine. I ran my ATTiny85 version using polling for months. I went down this path to set myself up for bigger projects in the future, I'm a glutton for punishment and as soon as I discovered it wasn't easy I was fixated on getting it to work, and I may ultimately want to do more processing in the handler.

 

I suppose of the options, polling the TCON_IE0 might be the most direct. This allows the accelerometer to signal at its interrupt time and minimizes any delay (which is really insignificant anyway) between polling over I2C. Probably a more direct route than using an ISR also. I'll set that up and test it next.

 

Thanks!

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi All,

 

First, Simplicity Studio Configurator does allow you to set the edge vs. level sensitivity of the EXT0/EXT1 interrupts - it's just under "TIMER Setup" because in this case the settings are in the TCON register:

 

config_INT0edge.png

 

Second, there is no reason not to set the level as either active high or active low.  I agree that in many cases it would be a pain to use level sensitive interrupts for an external interrupt signal that may assert the interrupt signal for a long time, thereby causing your ISR to be continually invoked until the int signal is deasserted.  When used in edge-triggered mode, however, this is simply setting the polarity of the interrupt.  So, if your INT0/INT1 is edge-triggered, "active high" and "active low" will simply select whether the interrupt is triggered on a rising or falling edge, respectively.

 

Finally, this application (i.e. external sensor with interrupt line to signal when data is ready) is a prime example of why external interrupts like EXT0/EXT1 exist, and I think that using them in this context can provide significant advantages over a polling scheme.  The way I would handle this situation is to use an edge triggered external interrupt (i.e. INT0) fed from the sensor interrupt line.  In the ISR, I would set a global flag that would signal to my main loop that the sensor has some data to be read, and then the main loop could go about initiating and handling the I2C transfer between the MCU and the sensor.  

Anyway, that sounds very similar to what you are doing.  Let me know if you have any further questions.

 

Regards,

Mitch

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Another of life's mysteries solved Mitch, thanks!

 

What about the Configurator generating the SMB interrupt handler code that I need to delete? Or, maybe now that I have everything working I should test it to make sure it's no longer a problem. I suppose I'll do that.

 

Yes, that's exactly how I am configuring my application. It is how I've done similar things over the decades. Other than the SMB ISR mentioned above, I'm good for now.

 

Cheers,

Michael

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Ok, I'm using the edge configuration in Configurator and that works great. However, the generated SMB ISR does create a problem. It is continuously called and hangs the program. If I delete the routine complete, my code works great. And here is that pesky issue i mentioned. Also notice the Memory Space Overlap warning. I see this once and awhile. In both cases, a simple recompile clears it up. Any idea about this?

 

Screen Shot 2016-11-22 at 5.56.55 PM.png

Posts: 8,078
Registered: ‎08-13-2003

Re: I do have a problem setting registers to my device over I2C...

[ Edited ]

Ok, I'm using the edge configuration in Configurator and that works great. However, the generated SMB ISR does create a problem. It is continuously called and hangs the program.

see below

 

And here is that pesky issue i mentioned. Also notice the Memory Space Overlap warning. I see this once and awhile. In both cases, a simple recompile clears it up. Any idea about this?

you have, somehow managed to get two things in the same place, best guess you have interrupt 7 defined twice. once by you and once by the onfigurator

erik
Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

But this happens sporadically and simply starting a new build makes it go away. 

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


mhackney wrote:

But this happens sporadically and simply starting a new build makes it go away. 


I'm not sure that has really gone away ....

It seems to report as a warning, tho I'd call Memory Overlap more a fatal error.

 

If you ever get one of those, work back from the address to find/fix the duplicate interrupt handler.

 

If that warning nevertheless creates a hex file, and you run build again, with no changes to source or hex, it will appear to have no messages, simply because it figured it had nothing to do...

The error has not gone away, you still have source code with two colliding interrupt declarations, but one will have won.

 

Highlighted
<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


MitchC wrote:

  First, Simplicity Studio Configurator does allow you to set the edge vs. level sensitivity of the EXT0/EXT1 interrupts - it's just under "TIMER Setup" because in this case the settings are in the TCON register: 

 


Maybe SiLabs should fix that, so it is aliased in Interrupts and Timers

 

That way, someone who is configuring only an interrupt, is able to simply do exactly that, without requiring that they know that buried in Timer Settings, are important interrupt flags...

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Here's what I get after a make clean. I don't know exactly where to start and I certainly did not add code to service interrupts. However, I wonder if its related to the SMB interrupt handle that is generated that I have to remove in order not to hang? 

 

19:36:49 **** Build of configuration Keil 8051 v9.53 - Debug for project EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5 ****
make all 
PATH=BIN:/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/support/8051:/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/support/common/wine/opt/local/bin:/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/support/common/build:/usr/bin:/bin:/usr/sbin:/sbin
 
Building file: ../src/InitDevice.c
Invoking: Keil 8051 Compiler
wine "/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/keil_8051/9.53/BIN/C51" "@src/InitDevice.__i" || test $? -lt 2
fixme:heap:HeapSetInformation 0x0 1 0x0 0

C51 COMPILER V9.53.0.0 - SN: K1RLC-B02KAZ
COPYRIGHT Copyright (C) 2012 - 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.

C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)
Finished building: ../src/InitDevice.c
 
Building file: ../src/Interrupts.c
Invoking: Keil 8051 Compiler
wine "/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/keil_8051/9.53/BIN/C51" "@src/Interrupts.__i" || test $? -lt 2
fixme:heap:HeapSetInformation 0x0 1 0x0 0

C51 COMPILER V9.53.0.0 - SN: K1RLC-B02KAZ
COPYRIGHT Copyright (C) 2012 - 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.

C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)
Finished building: ../src/Interrupts.c
 
Building file: ../src/SMBus_Lib_Buffered_Master_Multibyte.c
Invoking: Keil 8051 Compiler
wine "/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/keil_8051/9.53/BIN/C51" "@src/SMBus_Lib_Buffered_Master_Multibyte.__i" || test $? -lt 2
fixme:heap:HeapSetInformation 0x0 1 0x0 0

C51 COMPILER V9.53.0.0 - SN: K1RLC-B02KAZ
COPYRIGHT Copyright (C) 2012 - 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.

C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)
Finished building: ../src/SMBus_Lib_Buffered_Master_Multibyte.c
 
Building file: /Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/sdks/8051/v4.0.2/Device/EFM8BB1/peripheral_driver/src/smb_0.c
Invoking: Keil 8051 Compiler
wine "/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/keil_8051/9.53/BIN/C51" "@lib/efm8bb1/peripheralDrivers/src/smb_0.__i" || test $? -lt 2
fixme:heap:HeapSetInformation 0x0 1 0x0 0

C51 COMPILER V9.53.0.0 - SN: K1RLC-B02KAZ
COPYRIGHT Copyright (C) 2012 - 2014 ARM Ltd and ARM Germany GmbH. All rights reserved.
*** WARNING C185 IN LINE 187 OF /Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/sdks/8051/v4.0.2/Device/EFM8BB1/peripheral_driver/src/smb_0.c: 'smbBusy': different memory space
*** WARNING C185 IN LINE 188 OF /Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/sdks/8051/v4.0.2/Device/EFM8BB1/peripheral_driver/src/smb_0.c: 'smbReq': different memory space
*** WARNING C185 IN LINE 189 OF /Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/sdks/8051/v4.0.2/Device/EFM8BB1/peripheral_driver/src/smb_0.c: 'smbReceive': different memory space
C51 COMPILATION COMPLETE.  3 WARNING(S),  0 ERROR(S)
Finished building: /Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/sdks/8051/v4.0.2/Device/EFM8BB1/peripheral_driver/src/smb_0.c
 
Building target: EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5.omf
Invoking: Keil 8051 Linker
wine "/Volumes/FastSD/Simplicity Studio/Simplicity Studio.app/Contents/Eclipse/developer/toolchains/keil_8051/9.53/BIN/LX51" "@EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5.lnp" || test $? -lt 2
fixme:heap:HeapSetInformation 0x0 1 0x0 0

LX51 LINKER/LOCATER V4.66.30.0 - SN: K1RLC-B02KAZ
COPYRIGHT ARM Germany GmbH 1995 - 2014
@EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5.lnp "./lib/efm8bb1/peripheralDrivers/src/smb_0.OBJ",
"./src/InitDevice.OBJ",
"./src/Interrupts.OBJ",
"./src/SMBus_Lib_Buffered_Master_Multibyte.OBJ"
TO "EFM8BB1_SMBUS_LIB_BUFFERED_MASTER_MULTIBYTE_5.OMF.CRBUILD" REMOVEUNUSED PRINT(.\EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5.m51) PAGEWIDTH (120) PAGELENGTH (65) CLASSES( CODE(C:0x0 - C:0x1ffe), CONST(C:0x0 - C:0x1ffe), ECODE(C:0x0 - C:0x1ffe), HCONST(C:0x0 - C:0x1ffe), XDATA(X:0x0 - X:0xff), HDATA(X:0x0 - X:0xff))

Program Size: data=26.5 xdata=12 const=0 code=1337
LX51 RUN COMPLETE.  0 WARNING(S),  0 ERROR(S)
Finished building target: EFM8BB1_SMBus_Lib_Buffered_Master_Multibyte_5.omf
fixme:heap:HeapSetInformation 0x0 1 0x0 0
wine(14396,0x401fb000) malloc: *** error for object 0xe8680003: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

19:36:54 Build Finished (took 5s.548ms)

I'm looking to find malloc_error_break but haven't yet.

Posts: 3,019
Registered: ‎02-07-2002

Re: I do have a problem setting registers to my device over I2C...


MitchC wrote:

First, Simplicity Studio Configurator does allow you to set the edge vs. level sensitivity of the EXT0/EXT1 interrupts - it's just under "TIMER Setup" because in this case the settings are in the TCON register:

 


I think this thread proves that the interrupt setting should not be in the "TIMER Setup". The fact that Intel chose long ago to use some free bits in an unrelated SFR, does not mean that a more abstract configuration tool should follow.

 


Finally, this application (i.e. external sensor with interrupt line to signal when data is ready) is a prime example of why external interrupts like EXT0/EXT1 exist, and I think that using them in this context can provide significant advantages over a polling scheme.  The way I would handle this situation is to use an edge triggered external interrupt (i.e. INT0) fed from the sensor interrupt line.  In the ISR, I would set a global flag that would signal to my main loop that the sensor has some data to be read, and then the main loop could go about initiating and handling the I2C transfer between the MCU and the sensor.  

 


Level interrupts are perfect when servicing an external device like this in the ISR. As long as the device wants service it will keep the interrupt active. If a new event arrives in the device while you're still servicing the previous the line will stay active and will not retrigger. After the ISR ends the level will retrigger the interrupt.

 

If you want to service the device in your main loop, an edge is probably better. But beware of missed 'edges'.

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @vanmierlo and @jmg,

 

You make a good point about the location of the INT0/INT1 edge/level configuration options in Configurator.  One factor in the current layout in Configurator may be that it was designed with the desire to preserve some relation to the way these configuration options are laid out in hardware, thus the reason for having the edge/level selection in the Timer section.  I will discuss this and your suggestion to alias these options in the External Interrupts tab with the Simplicity Studio/Configurator team and we will investigate the possibility of implementing this feature.  Thank you for that valuable feedback.

 

@mhackney- With regard to your memory overlap issue, as others on this thread have pointed out, this is likely due to a redefinition of the SMBus interrupt as a result of Configurator regenerating this interrupt.  As far as I know, Configurator has no knowledge of what software modules or libraries you are using in your code, thus it does not know that you are using the SMBus library, in which is defined and implemented an ISR for the SMBus to handle SMBus transactions.  Deleting the Configurator-generated ISR should fix this issue.

 

As for the malloc error, I am not sure of the cause.  It seems unlikely that you are using malloc in your MCU firmware (you are not, right?), and given that this error comes after the compilation and linking is complete, and is prefixed by 

 

wine(14396,0x401fb000)  

 

leads me to believe that this error is not associated with your MCU code at all, but with the toolchain or the Wine software compatibility layer you may be running on your system.  Is this the case?  What OS are you using?  I am not an expert in these matters, but I am leaning toward the belief that the malloc error is unrelated to your MCU code.

 

Regards,

Mitch

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Thanks Mitch, 

Even deleting the Configurator generated ISR gives me those warnings.

 

I am not using malloc()

 

I am not running wine explicitly, perhaps the Mac ISX version of Eclipse or the tools use it though. I am in Mac OSX 10.12.1. I noticed the wine reference and my first thought was that it was an IDE issue.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

I continue to be perplexed! I restructured a bit of my main() to remove some LED blinking code and add some better error handling. I did not touch anything in Configurator. Now, when I run, the interrupt is not caught. BUT if I touch the P0.7 to ground, it is caught - similar to what I reported above. This kind of stuff drives me crazy as it defies logic.

Posts: 8,078
Registered: ‎08-13-2003

Re: I do have a problem setting registers to my device over I2C...

I continue to be perplexed! I restructured a bit of my main() to remove some LED blinking code and add some better error handling. I did not touch anything in Configurator. Now, when I run, the interrupt is not caught. BUT if I touch the P0.7 to ground, it is caught - similar to what I reported above. This kind of stuff drives me crazy as it defies logic.

 

since the pin is (weakly) pulled high pulling it high will not generate an interrupt

 

pulling it low will

if active low interrupt when pin is grounded

if active lhigh interrupt when pin grounded is removed

erik
Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Ok, well I did a clean rebuild and now it is seeing the interrupt! 

 

But let me ask, what would be the most reliable way to catch this interrupt in terms of configuration. The accelerometer sets it's output pin high to signal the interrupt and holds it high until its INT register is cleared. These are "slow" events that only occur when the 3D printer taps its nozzle to the bed - once every second or more and only during a probe sequence. 

 

I currently have P0.7 configured as:

 

Open Drain

Latch High

Active Low

Edge Triggered

 

 

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Well, I discovered why the interrupts stopped working and its related to pin configuration. Basically, I had some code to poll the accelerometer. This code "sees" the interrupt even if the trigger was not caught by the interrupt handler. So. it would see the interrupt, clear it and it seems to be at that point (clearing the accelerometer interrupt register which causes the pin to drop to low) that my interrupt handler is called. With this code removed, the interrupt is generated but raises high and the rising edge is not caught for some reason. 

 

So the question still remains, what's the best configuration for this pin (0.7)?

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Ugh, now I'm back to this issue. What does this mean and what can I do about it? I've shut down and reloaded SS and I've power cycled the 2020A several times. I've tried running the blinky example too. I don't know what else to do?

 

Screen Shot 2016-11-23 at 12.03.27 PM.png

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

First, if your accelerometer drives its interrupt signal high when it wants service, you want your INT0 to be configured as active high as opposed to active low.  Second, you want your PnMDIN register bit set to 1 for digital operation, and PnMDOUT = 0 for open-drain.  Set the latch to 1.  

 

If the accelerometer does not drive the pin low when it is not requesting service, the internal weak pullup on the pin will pull the pin high, which will mask an interrupt request event (i.e. when the accel drives the pin high).  If this is the case, you will want to disable the weak pullups in the XBR2 register.  If the accel. drives low, it will be able to overcome the weak pullup and you shouldn't have a problem.

 

I hope that helps.

 

Regards,

Mitch

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Thanks Mitch, I was actually in the process of trying exactly what you suggest but I am dead in the water with the issue I reported in my previous post. Nothing is getting me out of this problem.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Mitch or anyone, I really need help figuring out this debug launch issue that I reported above with a screen shot of the dialog. Nothing I've tried has worked. 

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

A couple things to try:

 

1) Close Simplicity Studio, then use Activity Monitor or your OS equivalent of Task Manager to locate and kill any instances of "Siagent" that are running.

 

2) Please create a .zip of your log files by going to Help -> Support -> Report bug.  If you can attach that information it will help me determine what is wrong and I can pass that info to the Simplicity Studio team.

 

Thanks,

Mitch

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


mhackney wrote:

Mitch or anyone, I really need help figuring out this debug launch issue that I reported above with a screen shot of the dialog. Nothing I've tried has worked. 


Did you try a reboot of the Mac ?

That sounds like an Operating System / Wine / SS 'ball drop', and restart of SS alone may not be enough.

Do you have a Windows PC you can use as a second opinion ?

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


... it seems to be at that point (clearing the accelerometer interrupt register which causes the pin to drop to low) that my interrupt handler is called. With this code removed, the interrupt is generated but raises high and the rising edge is not caught for some reason. 

 

So the question still remains, what's the best configuration for this pin (0.7)?


Sounds like you have a Falling Edge when you need Rising.

The default edge mode for a 8051 is Falling Edge  =\_.

 

In the SiLabs parts, there is an IN0PL bit, that can flip the PIN level, and this gives _/= INT

 

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

[ Edited ]

Here's the log files Mitch. 18 processes needed to be killed.

 

I can now debug again but of course, my program is misbehaving.

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

Hi @mhackney,

 

I will pass along the log file to the Simplicity Studio team for investigation.  For now, I'm glad you are again able to debug.  If the same problems occurs again before we get a chance to investigate these logs, kill the processes again and resume development if possible.  Best of luck!

 

Regards,

Mitch

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Thanks Mitch. Back to the interrupt. You wrote earlier:

 

First, if your accelerometer drives its interrupt signal high when it wants service, you want your INT0 to be configured as active high as opposed to active low.  Second, you want your PnMDIN register bit set to 1 for digital operation, and PnMDOUT = 0 for open-drain.  Set the latch to 1.  

 

If the accelerometer does not drive the pin low when it is not requesting service, the internal weak pullup on the pin will pull the pin high, which will mask an interrupt request event (i.e. when the accel drives the pin high).  If this is the case, you will want to disable the weak pullups in the XBR2 register.  If the accel. drives low, it will be able to overcome the weak pullup and you shouldn't have a problem.

 

I am using Configurator and know how to set active high and digital open drain and latch. I don't know how to disable the weak pullup in Configurator and I looked around. Where can I find that? In the near term to test I'll tweak the bit manually in the generated Init code but it would be good to have this a permanent change.

Posts: 201
Registered: ‎08-19-2015

Re: I do have a problem setting registers to my device over I2C...

To disable weak pullups using Configurator, click on "Port I/O" in the Outline tab.  Then you can change the pullup settings below in the Properties tab.  See screenshot below.

 

Configurator_diasable_pullups.png

 

Regards,

Mitch

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...

[ Edited ]

 

I am using Configurator and know how to set active high and digital open drain and latch. I don't know how to disable the weak pullup in Configurator and I looked around. 


You should only need to disable Weak Pullup, and add an external pull down, if the Sensor is a Open-Drain-P-FET (ie can only pull hi, floats otherwise), which would be rare.

 

Your post #32 above, suggests it can drive H-L fine, so this should not be required.

 

You will need to flip the edge polarity, to Rising to get the right phase of operation.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

How does one flip the edge polarity? Can it be done in the Configurator.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

I just have to chuckle at my bad luck...

 

Now that I can debug again, I am trying to update the interrupt as described above. It's straightforward except the flipping edge polarity - I don't know how to do that yet, I'll read the docs. But, now I run in debugger, step through my code and the first I2C use to fetch the WHO_AM_I byte succeeds and returns the expected byte. I continue to step into my accelerometer initialization code and the very first I2C call to clear the interrupt source on the accelerometer generates an error as seen in the global numErrors value being > 0. This is the normal sequence for initializing this accelerometer and is exactly how I did it on the Arduino and has been working on this 2020A board after I made the updates yesterday to write two bytes (register to set and the value to set it to). Now all of a sudden, it is failing. I am going to reset all of the interrupt config stuff although I don't think that's the issue - but maybe it is.

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Ok, I reset the EXT 0 INT back to (in Configurator):

 

Analog->ADC 0->Port I/O properties: Pull-upsenabled (weak pullup)

Core->External Interrupts: INT0 Polarity: Active high on P0.7

Core->Interrupts: External 0 Interrupt Enabled

Timers->Timers: External Interrupt Settings-> INT0 Edge Triggered

 

Now I'm back to "working" in that the initialization I2C code is succeeding. But I have to manually trigger the interrupt by touching P0.7 to GND.

 

I think the raising edge and active high make sense but I don't know how to set raising edge yet.

Posts: 3,019
Registered: ‎02-07-2002

Re: I do have a problem setting registers to my device over I2C...

When you touch P0.7 to GND, have you looked at VDD on the scope? I expect you're pulling the power down completely because I expect the INT output is PUSH-PULL. That is a good way to fry this output pin.

<a href="http://community.silabs.com/t5/Welcome-and-Announcements/Community-Ranking-System-and-Recognition-Program/m-p/140490#U140490"><font color="#000000"><font size="2">Hero</font></font> </a> jmg
Posts: 1,154
Registered: ‎04-27-2004

Re: I do have a problem setting registers to my device over I2C...


I think the raising edge and active high make sense but I don't know how to set raising edge yet.


See post above, you need IN0PL bit, in IT01CF

 

Also see Table 11.3. INT0/INT1 configuration, where it shows 

 

IT0=1  &   IN0PL = 1    -> Interrupt on rising edge _/=

 

I'm not sure of the Config terminologies, but see what it does to IT01CF,TCON to check you do have _/=

Posts: 91
Registered: ‎11-07-2016

Re: I do have a problem setting registers to my device over I2C...

Section 11.3.4 INT0 and INT1 in the EFM8BB1 Reference Manual:

 

INT0 and INT1 are configurable as active high or low, edge- or level-sensitive. The IN0PL and IN1PL bits in the IT01CF register select active high or active low; the IT0 and IT1 bits in TCON select level- or edge-sensitive. The table below lists the possible configurations.

 

Table 11.3. INT0/INT1 configuration

 
and my configuration is the third row in the table.
 

So I think I get that simply by setting active high and trigger on edge? If so, that is not working.

 

Here's from the generated InitDevice.c:

 

IT01CF = IT01CF_IN0PL__ACTIVE_HIGH | IT01CF_IN0SL__P0_7 | IT01CF_IN1PL__ACTIVE_LOW | IT01CF_IN1SL__P0_0;

 

TCON |= TCON_IT0__EDGE | TCON_TR1__RUN;

 

So that should do it shouldn't it? Now that I pay attention to the behavior, maybe this will help:

 

If I touch P0.7 to GND and hold it there, no interrupt is triggered. It's when I disconnect it from GND that the interrupt is triggered. Nothing happens when I touch and hold on 3v3 or when I release.

 

So that seems to indicate that I am interrupting on raising edge when I do it manually. I'll go through my code again to make sure that I am clearing the accelerometer's interrupt register. It has to be something simple.