PCINTs work with running WDT, otherwise not

Go To Last Post
32 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, I have been struggling for 2 days to understand how my external PCINTs on port B and port C do work when the WDT is initialized and running, but NOT when the WDT is not initialized at all or stopped?

- I have an ATtiny1634 chip, tried already 3 of them and the same issue happens every time the WDT is switched off (so my initial suspicions that I somehow burnt the inputs @ the PCINT pins were discarded)

- I tried to use different pins (combinations of pins as I currently need 2 out of 3 which are free) on port B and port C: PB3 (pin 16 with PCINT11), PC0 (pin 15 with PCINT12), and PC2 (pin 13 with PCINT14) - the issue appears no matter the pins chosen

- @ the start of my code I define my inputs as usually, e.g.

#define INPUT_PIN_FROM_MC5_IMOB_SCK	PINB3
#define INPUT_PIN_FROM_MC5_IMOB_RESTART	PINC0

In the main()-function I enable the PCINTs; then if I initialize the WDT, my program later works as expected (PCINTs on port B or C react and the corresponding ISRs are executed); if I don't initialize the WDT, then PCINTs on port B or C do not react later and the ISRs are not executed ?? Before the endless while-loop I enable timer0 for CTC mode on pin PA5 (OC0B) to generate a square wave signal for my antenna to energize and read an RFID tag whose bits are received and read in @ pin PA6 where PCINT6 (PCINT0 group) is activated. In the endless loop I wait for a flag to be set, which happens within the PCINT0-ISR (this one always works, no matter the WDT is on or off !!)

int main ( void ) {
	<uart is initialized ...>
	<output pins are set ...>
	enablePCINTinterrupts ();
	initWDT (); // !! if WDT is on, PCINTs on port B and C work; if WDT is off, they don't ??
        initTagSearching ();
	while ( 1 ) {
		if ( tagReadingComplete ) {
		    tagReadingComplete = FALSE;
		    <code to display tag ID ..., then program waits for inputs (HIGH level) on PCINT pins which is handled in the respective ISRs >
		}
		wdt_reset();
	}

The functions look as follows:

void initWDT ( void ) {
	cli();
	wdt_reset();
	WDTCSR = ( 1 << WDE ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 );
	sei();
}
void enablePCINTinterrupts ( void ) {
	cli();
	GIMSK  = ( 1 << PCIE2 ) | ( 1 << PCIE1 );	// enable PCINT group interrupts ( PCINT[17:12] && PCINT[11:8] )
	PCMSK2 = ( 1 << PCINT12 );				    // enable PCINT on pin 15/PC0
	PCMSK1 = ( 1 << PCINT11 );					// enable PCINT on pin 16/PB3
	sei();
}

So, basically if I initialize the WDT with my function

initWDT ();

PCINT1-ISR and PCINT2-ISR get executed; otherwise not.

Also, if I switch off the WDT with timed sequence after I have enabled it, then PCINT1-ISR and PCINT2-ISR do not work either.

int main ( void ) {
    ...
    initWDT ();
    initTagSearching ();
    stopWDT ();
	while ( 1 ) {
	    ...
void stopWDT ( void ) {
	wdt_reset();
	MCUSR &= ~ ( 1 << WDRF );
	CCP = 0xd8;
	WDTCSR &= ~ ( ( 1 << WDE ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 ) ) ;
}

The fuses of ATtiny are set as follows:

- extended: 0xf5

- high:         0xdd

- low:          0xef

Could anybody help ? I still don't manage. Thanks in advance.

This topic has a solution.
Last Edited: Thu. Nov 28, 2019 - 09:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If you ever use the pattern:

void function() {
    cli();
    stuff()
    sei();
}

then consider:

void function() {
    ATOMIC_BLOCK() {
        stuff();
    }
}

with that you have the option of putting SREG (specifically I) back the way it was rather than forcing sei() when the entry state might not have been sei() already !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Assuming for a minute that your toolchain is gcc, it has built in libs for performing the time critical functions of enabling/disabling WDT that you should be using rather then your own c code, as the optimization of the compiler can do strange things to the order of code that will not guarantee the needed timing is met.  

The gcc users of this forum can provide details if needed, just ask.

 

another thing I just thought of, are you doing any sei() or cli() calls in your ISRs?   You should not be, as the AVR takes care of that for you!!!

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

Last Edited: Wed. Nov 13, 2019 - 01:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
Assuming for a minute that your toolchain is gcc,
All the clues are there!

int main ( void ) {
void initWDT ( void ) {
	cli();
	wdt_reset();
	WDTCSR = ( 1 << WDE ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 );
	sei();
}

I don't know of many AVR compilers where the return from main() is "int" not "void" and that offer cli()/sei()/wdt_reset() so, personally, I'm in no doubt this is GCC - hence why I suggested ATOMIC_BLOCK() too.

 

GCC's provided functions for watchdog are here:

 

https://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, clawson, thanks for your response. I replaced all "cli();" + "sei();" calls within my function bodies with the recommended "ATOMIC_BLOCK(ATOMIC_RESTORESTATE)". Also checked the options under "Toolchain -> AVR/GNU C Compiler" in Atmel Studio 7 and found "-std=gnu99" which should satisfy the requirement to use the header as described in the docs @ https://www.nongnu.org/avr-libc/...

However, there is no change in the result: the same thing happens. I started reducing the code by commenting out, and currently I only try to use pin PB3 as PCINT source:

void enablePCINTinterrupts ( void ) {
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		GIMSK  = ( 1 << PCIE1 );// | ( 1 << PCIE2 );
		//PCMSK2 = ( 1 << PCINT12 );
		PCMSK1 = ( 1 << PCINT11 );		
	}
}

If no watchdog is running, the PCINT1 ISR (source PCINT11) does not execute. If I turn the watchdog on, it does. This is the only difference between working and non-working code, no other parallel software / hardware changes) ?? I commented out also the "wdt_reset()" within the "initWDT()" function to possibly try to see if it makes any difference, but it does not; with / without "ATOMIC_BLOCK" does not change anything either. So currently the watchdog init function contains a single line of code which makes the difference between working and non-working code, namely:

void initWDT ( void ) {
	//ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		//wdt_reset();
		WDTCSR = ( 1 << WDE ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 );
	//}
}

- Also checked the alternate functions of PB3 (ADC8/OC1A/PCINT11), but there is nothing watchdog related that I can see.

- Also using both my "initWDT ()" and the corresponding built-in "wdt_enable(WDTO_2S);" work the same for a 2s TO period for the WDT, so here again is not the issue.

The strangest thing which I find stunning is that the lack of something leads to working code and its presence/addition to non-working, I am logically totally puzzled here.

Do you possibly have another idea how the watchdog coudl mix with PCINTs, specifically PCINT1 group / PCINT11 on PB3 as currently this the one I am left with (all the others not used / commented out) ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

- using the built-in functions/macros ("ATOMIC_BLOCK", "wdt_enable()") does not change the issue

- "no cli() / sei()" in the ISRs has no effect either

Last Edited: Thu. Nov 14, 2019 - 01:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is unhandled ISRs - what do you see if you handle ISR(BADISR_vect) as explained in the manual here:

 

https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

clawson wrote:
My guess is ...

Yes, a lot of guessing.  Let's see a complete test program that demonstrates the situation.  Tell fuses and build options.  Tell toolchain and version.  Tell how you are testing; tell what you expect to happen; tell what IS happening.  Kind of the standard problem investigation set of requested/needed information.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you using sei() or cli() calls in any ISR()'s ???

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

ki0bk wrote:
Are you using sei() or cli() calls in any ISR()'s ???
I'm with Lee:
theusch wrote:
Let's see a complete test program that demonstrates the situation.
which would take all the guess work out of this ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Hi, clawson / ki0bk / theusch,

thanks all for your replies.

- main.c file is attached (line 218 makes the difference [initWDT ();])

- with regard to Atmel Studio I haven't changed any settings as I currently consider myself a newbie and still don't dare :-)

- here a screenshot of Atmel Studio:

- screenshot of AVR/GNU C Compiler options from the Project properties Tool-chain option:

- screenshot of AVR/GNU Linker:

- AVR/GNU Assembler:

- idea and procedure behind the program is to generate square wave @ 125 KHz using OC0B (PA5) pin with CTC mode; the antenna feeds then the 125 KHz tag; the tag modulates the input wave, and those modulations (0s and 1s via an op amp) are received @ pin PA6 where PCINT6 is enabled to register the voltage level transitions between HIGH and LOW. When all tag bits are received and stored, wave generation and timer0 are stopped and a flag is raised by PCINT0-ISR for the main(). When the main() sees the set flag, it knows a tag is read; the parity of the received bits is then checked: if the parity is not OK, tag searching is restarted by the software; it parity is OK, 1st bit of the tag ID is presented on pin PA1 (HIGH for 1, LOW for 0) and then the program waits for HIGH level on PB3 where PCINT11 is enabled with the idea to send the other bits of the tag ID bit by bit whenever HIGH level is detected on PB3. Pin PB3 is pulled down by an external 10k resistor, and there is an open jumper wire end after a 1k resistor; I attach the open wire end to +V to simulate the HIGH level signals that should come from the other ATmega2560 uC. When I do this and the WDT is on, whenever I connect the open wire end to +V the HIGH level is detected and the PCINT1-ISR is executed and the tag bits are read and displayed bit by bit; if the WDT is not on, this does not function:

----------------

| ATtiny1634 | PB3---- |----- 1k ---- open jumper wire end

-----------------             |

                                10K

                                  |

                               GND

I touch this jumper wire open end to +V to get HIGH level: with WDT on, it makes PCINT1-ISR execute; without it, nothing happens. I do this to simulate a HIGH level coming from the other uC (ATmega2560) which should request the tag ID read by the ATtiny bit by bit and then store it by itself.

- I replaced all cli() / sei() calls with the ATOMIC_BLOCK(RESTORESTATE), but those were used by functions outside the ISRs.

Attachment(s): 

Last Edited: Fri. Nov 15, 2019 - 02:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I think what is more along the lines of what is wanted-

 

#include <avr/io.h>
#include <avr/interrupt.h>
int main ( void ) {
    DDRA = 1<<1; //PA1 = led
    GIMSK  = ( 1 << PCIE1 );
    PCMSK1 = ( 1 << PCINT11 );
    sei();
    for(;;){}
}
ISR(PCINT1_vect){
    PINA = 1<<1; //toggle led
}

 

That is something no one has to take any time to figure out, and you then have a baseline to work from. It works, or it doesn't work (I don't know if code is correct, but you get the idea). If it works, then you know you have something wrong in all your other code. If it doesn't work, then it would be odd, but there are not many possibilities to figure out whatever they may be, and those with similar hardware can easily test the same code.

 

I tried in mplabx simulator (by setting pb3 to output, and toggle pin to simulate pcint11), but simulator does not work. Maybe atmel ide would work.

Last Edited: Fri. Nov 15, 2019 - 03:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

blqsa4ko wrote:
I touch this jumper wire open end to +V to get HIGH level

You are likely to get multiple "hits" with this bouncing signal...

blqsa4ko wrote:
it makes PCINT1-ISR execute; without it, nothing happens.

...so now we need to dig through the code to see how it reacts with multiple hits, including both odd and even number.

 

As mentioned, the process of narrowing down to a small test case program will often help to uncover the problem situation.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

blqsa4ko wrote:
When I do this and the WDT is on, whenever I connect the open wire end to +V the HIGH level is detected and the PCINT1-ISR is executed and the tag bits are read and displayed bit by bit; if the WDT is not on, this does not function:

Indeed, think about what happens with multiple hits.

 

Try a test with a simpler ISR to "prove" that nothing happens.

 

When it "works", how fast do you get the indication?  (the WDT is set for 2 seconds, right?)

 

Trap the reset cause, and see if is resetting and starting over due to the watchdog.

 

Wow--a timer tick every 4us, with non-trivial action?  Do you really expect that to work?  Consider how far behiind you will get when e.g. the extensive PCINT0 fires.

 

You have -Wall ... are you getting any build warnings?

 

When you enable your bank 1 pin-change interrupt, you are turning off the bank 0 action.  Is that desired?  [probably the functions are declared in a different order?]

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

- If I define ISR(BADISR_vect), comment out ISR(PCINT1_vect) code, and still enable PCINT1, then the code within ISR(BADISR_vect) does not execute when required, e.g. when PB3 is connected to +V (no other interrupts enabled).

-On the other hand, if I define ISR(BADISR_vect), comment out ISR(PCINT0_vect) code, and still enable PCINT0, then the code within ISR(BADISR_vect) gets executed instead of the ISR(PCINT0_vect) code when required, e.g. when I approach the tag to the antenna (which normally triggers the code within ISR(PCINT0_vect)

 

Hence, the way I understand the idea behind ISR(BADISR_vect), the PCINT1 on PB3 just does not trigger, even though enabled and even though trigger condition is there, hence the substitution code for it within ISR(BADISR_vect) also does not execute.

...

Just tried the same procedure with PC0 and it works: If I define ISR(BADISR_vect), comment out ISR(PCINT2_vect) code, and still enable PCINT2, then the code within ISR(BADISR_vect) gets executed when required, e.g. when PC0 is connected to +V, hence PCINT2 and PC0 work, but PCINT1 and PB3 don't

Last Edited: Mon. Nov 18, 2019 - 02:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do indeed get a bouncing signal with multiple hits, but when the WDT is on I do also get multiple tag bits being processed, e.g. the ISR(PCINT1_vect) seems to execute as many times. When the WDT is off, not a single bit is gotten, e.g. ISR(PCINT1_vect) does not execute a single time

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

- no build warnings:

------ Rebuild All started: Project: RFIDreaderForMC5restartPCINT1sckPCINT2, Configuration: Debug AVR ------
Build started.
Project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj" (Clean target(s)):
Target "Clean" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\koko\Desktop\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2.cproj" (entry point):
	Task "RunCompilerTask"
		Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
		C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe clean 
		rm -rf  main.o   
		rm -rf  main.d   
		rm -rf "RFIDreaderForMC5restartPCINT1sckPCINT2.elf" "RFIDreaderForMC5restartPCINT1sckPCINT2.a" "RFIDreaderForMC5restartPCINT1sckPCINT2.hex" "RFIDreaderForMC5restartPCINT1sckPCINT2.lss" "RFIDreaderForMC5restartPCINT1sckPCINT2.eep" "RFIDreaderForMC5restartPCINT1sckPCINT2.map" "RFIDreaderForMC5restartPCINT1sckPCINT2.srec" "RFIDreaderForMC5restartPCINT1sckPCINT2.usersignatures"
	Done executing task "RunCompilerTask".
Done building target "Clean" in project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj".
Done building project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj".

Build succeeded.
------ Rebuild All started: Project: RFIDreaderForMC5restartPCINT1sckPCINT2, Configuration: Debug AVR ------
Build started.
Project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\koko\Desktop\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2.cproj" (target "Build" depends on it):
	Task "RunCompilerTask"
		Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
		C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 4 --output-sync 
		Building file: .././main.c
		Invoking: AVR/GNU C Compiler : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=attiny1634 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny1634" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c" 
		Finished building: .././main.c
		Building target: RFIDreaderForMC5restartPCINT1sckPCINT2.elf
		Invoking: AVR/GNU Linker : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -o RFIDreaderForMC5restartPCINT1sckPCINT2.elf  main.o   -Wl,-Map="RFIDreaderForMC5restartPCINT1sckPCINT2.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=attiny1634 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny1634"  
		Finished building target: RFIDreaderForMC5restartPCINT1sckPCINT2.elf
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "RFIDreaderForMC5restartPCINT1sckPCINT2.elf" "RFIDreaderForMC5restartPCINT1sckPCINT2.hex"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "RFIDreaderForMC5restartPCINT1sckPCINT2.elf" "RFIDreaderForMC5restartPCINT1sckPCINT2.eep" || exit 0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "RFIDreaderForMC5restartPCINT1sckPCINT2.elf" > "RFIDreaderForMC5restartPCINT1sckPCINT2.lss"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "RFIDreaderForMC5restartPCINT1sckPCINT2.elf" "RFIDreaderForMC5restartPCINT1sckPCINT2.srec"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "RFIDreaderForMC5restartPCINT1sckPCINT2.elf"
		   text	   data	    bss	    dec	    hex	filename
		    376	      0	     68	    444	    1bc	RFIDreaderForMC5restartPCINT1sckPCINT2.elf
	Done executing task "RunCompilerTask".
	Task "RunOutputFileVerifyTask"
				Program Memory Usage 	:	376 bytes   2,3 % Full
				Data Memory Usage 		:	68 bytes   6,6 % Full
	Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Avr.common.targets" from project "C:\Users\koko\Desktop\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2\RFIDreaderForMC5restartPCINT1sckPCINT2.cproj" (entry point):
Done building target "Build" in project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj".
Done building project "RFIDreaderForMC5restartPCINT1sckPCINT2.cproj".

Build succeeded.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

- when it works [when the WDT is on], I get the bits immediately (for as long the signal bounces, the ISR gets executed and the bits processed)

- program does NOT reset ! it runs, but does not react to PCINT on PB3

- if WDT is on (set to 2s TO period), and I don't clear the timer with wdt_reset(), then it resets every 2s as expected => no issue here

- the 4 us timer does work, it's been used like this for like 4-5 months now without any issues, but I confess it's been always at the edge :-) timer0 gets immediately switched off when a tag is detected, hence it should not influence bit reading via PCINT1 on PB3 which happens after the tag is read

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Already tried with a similar simple program using timer1 to toggle the pin ... Anyway, following your suggestion, this simple program also works when the watchdog is on, but not when it is off:

int main ( void ) {
    initWDT (); // WITH THIS LINE IT WORKS / WITHOUT IT, IT DOES NOT !     https://www.mikrocontroller.net/topic/65923 -> GCC schreibt das CLI an eine völlig andere Stelle und statt 6 Zyklen sind's nun viele hunderte und ich such mir nen Wolf, warum Interrutps verloren gehen !! Der Compiler selbst weiß nicht, daß das cli() und das sei() in einem Zusammenhang stehen. Er weiß auch nicht, daß der Code dazwischen auch in einem Zusammenhang dazu steht. Er weiß (durch volatile), daß er das cli() und das sei() so wie im Code ausführen muß, aber er weiß aufgrund des fehlenden volatile nicht, daß er das mit der Zuweisung und der Division auch tun muß.
    DDRA = ( 1 << 1 );
    GIMSK = ( 1 << PCIE1 );
    PCMSK1 = ( 1 << PCINT11 );
    sei();
    //stopWDT ();
    for ( ; ; ) {
        ;
    }
}
ISR(PCINT1_vect){
    PORTA ^= ( 1 << 1 ); //toggle white led
}

Had already tried the Simulator of Atmel Studio: code works as expected: if I toggle manually bit 3 of PINB, then the program flow gets into the PCINT1_ISR, so simulation didn't help me either solve the issue.

 

I already know there is something odd happening, it's just that I can't figure it out myself, hence the thread in the forum. What do you mean with "there are not many possibilities" ? Which are those possibilities ? I would try them out

 

 

Last Edited: Tue. Nov 19, 2019 - 11:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

blqsa4ko wrote:
Had already tried the Simulator of Atmel Studio: code works as expected: if I toggle manually bit 3 of PINB, then the program flow gets into the PCINT1_ISR, so simulation didn't help me either solve the issue.
theusch wrote:
Indeed, think about what happens with multiple hits.
"Buttons" bounce.

 

I still say that you need to try with a simpler ISR and count how many times it actually entered.

 

And I still say that an interrupt every 4us might appear to you to be working, but there is no way even at 20MHz that you are going to catch up on that timing when the action ISRs take many many microseconds.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>this simple program also works when the watchdog is on, but not when it is off:

 

If you cannot get pcint11 to fire in the simple test, your task is to not start adding more unrelated code, but to figure out why the interrupt cannot be fired. You are attempting to pinpoint the problem, so narrow it down and do not increase your possibilities. Is the PCIE1 bit getting set? is the PCINT11 bit getting set? Is the GIE bit getting set? Does the watchdog register look normal? (if on, indicates your watchdog fuse may be set to wdton). What does the assembly listing show? Am I using the wrong pin diagram? What is the voltage on pb? What are the reset flags showing? Are there brownouts? Did I forget to add bypass cap on vcc? etc.

 

>if I toggle manually bit 3 of PINB, then the program flow gets into the PCINT1_ISR, so simulation didn't help me either solve the issue.

 

But it probably shows your code generation is ok for the simple example anyway. So do the same thing on the real hardware. Forget about whatever is hanging on pb3 for the moment, and just duplicate what the simulator was doing (pb3 output, toggle it via pinb3 to get the isr to fire). Maybe you discover you are using the wrong pin. pb3 is pb3 on both the dip and qfn part, so regardless of whether you have them mixed up somehow externally, it is the same pb3 internally and doing the software trigger eliminates the external to some degree. You can also step through code and will have control of when the irq is fired, can see what pb3 is doing along with the rest of the registers needed to make pcint1 it work.

 

You have already narrowed your problem down, or at least found one problem. Doesn't matter at the moment what else you have going on for problems, you should be able to get a pcint1 isr to fire using minimal code, and the as7 simulator should be good enough to where your hardware should act the same. I wouldn't touch anything else until I could get that working correctly. It may lead you to your main problem, or may not, but you really can't go further until that is settled.

 

I would also throw any watchdog code in the dumpster for now- don't even allow it in commented out code. No need to complicate things while troubleshooting. Once everything is working as it should, then you can start messing with the watchdog. There is no need to have the watchdog throwing resets at you while you are trying to figure things out. You are not checking any reset flags, so you will never know and it may be masking problems or creating others.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried with simpler ISRs, for both pins (PC0 & PB3), using the following:

ISR(PCINT1_vect){
	isrCount++;
	if ( PINB & ( 1 << PINB3 ) )
		LED_OUTPUT_PORT |=   ( 1 << 0) ;	// white LED on
	else
		LED_OUTPUT_PORT &= ~ ( 1 << 0) ;	// white LED off
}

ISR(PCINT2_vect) {
	isrCount++;
	if ( PINC & ( 1 << PINC0 ) )
		LED_OUTPUT_PORT |=   ( 1 << 1) ;	// red LED on
	else
		LED_OUTPUT_PORT &= ~ ( 1 << 1) ;	// red LED off
}

and used a counter variable to check how many times the program enters in each ISR respectively.

And the same issue reappears:

1. when the WDT is off:

- connecting PC0 to 3,3V makes the PCINT2 ISR execute, and the counter variable (isrCount, defined as char) increments (if I display "isrCount" via UART, I get all the ASCII symbols repeatedly)

- connecting PB3 to 3,3V does not cause PCINT1 ISR to execute, and the counter variable does not change (also nothing gets displayed via UART)

2. when I switch the WDT on, both pins work as expected:

- connecting PC0 to 3,3V makes the PCINT2 ISR execute, and the counter variable increments whenever contact to 3,3V is made

- connecting PB3 to 3,3V makes the PCINT1 ISR execute, and the counter variable increments whenever contact to 3,3V is made

 

I decided to check the working of both pins without interrupts, just polling, moving the respective ISR codes into main() - this is the whole program now:

int main ( void ) {
    DDRA = ( 1 << DDRA1 ) | ( 1 << DDRA0 ) ;     // both pins driving the LEDs are outputs
    for ( ; ; ) {
        if ( PINB & ( 1 << PINB3 ) )
            PORTA |=   ( 1 << 0 ) ;    // white LED on
        else
            PORTA &= ~ ( 1 << 0 ) ;    // white LED off
        
        if ( PINC & ( 1 << PINC0 ) )
            PORTA |=   ( 1 << 1 ) ;    // red LED on
        else
            PORTA &= ~ ( 1 << 1 ) ;    // red LED off
    }
}

and the same happens:

- when the WDT is on: connecting either PC0 or PB3 to 3,3V makes the respective LED light up (so both pins do work)

- when the WDT is off: only connecting PC0 to 3,3V makes its LED light up; but connecting PB3 to 3,3V does not light its LED up => the PB3 pin as input just never reads the HIGH voltage level 3,3V even though connected to 3,3V when the WDT is off ??

This explains why the PCINT interrupt never got executed, but how can I explain PB3 not working as input when no WDT is running ?? (no interrupts enabled / I think the program can't be simplified more than that / 3rd ATtiny1634 chip and 2nd PCB I try ) I ran out of ideas :(

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I congratulate you on working to simplify the situation.

 

-- Tell your fuses for both cases

-- Show the complete program for "WDT on".  Surely there must be code to initialize the watchdog, and to do WDR.

-- As a sanity check, measure the voltage RIGHT ON THE PB3 PIN.

-- What are the results with other pins?  Another pin on port B?  Another pin on port C?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-- fuses are:

 

Originally the fuses were with "BODPD" and "BODACT" enabled, but because of "curtvm"'s most recent comment about checking reset flags I decided to switch BOD bits off to exclude the possibility of BOD reset while testing. Anyway, switching them on again does not change anything (already tried out), switching them off either. So, currently both BOD bits are off.

 

-- program for "WDT on":

void initWDT ( void ) {
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		wdt_reset();
		WDTCSR = ( 1 << WDE ) | ( 1 << WDP2 ) | ( 1 << WDP1 ) | ( 1 << WDP0 );
	}
}
int main ( void ) {
    DDRA = ( 1 << DDRA1 ) | ( 1 << DDRA0 ) ;
    initWDT ();
    for ( ; ; ) {
        if ( PINB & ( 1 << PINB3 ) )
		LED_OUTPUT_PORT |=   ( 1 << 0 ) ;	// white LED on
	else
		LED_OUTPUT_PORT &= ~ ( 1 << 0 ) ;	// white LED off

	if ( PINC & ( 1 << PINC0 ) )
		LED_OUTPUT_PORT |=   ( 1 << 1 ) ;	// red LED on
	else
		LED_OUTPUT_PORT &= ~ ( 1 << 1 ) ;	// red LED off
    }
}

-- voltage RIGHT ON THE PB3 PIN ( 1K resistor between open end and PB3; PB3 pin is also grounded via 10K resistor ):

        ++ with WDT on: 3,078 V (+V = 3,388 V)

        ++ with WDT off: 2,805 V (+V = 3,405 V)

   => ca. 0,3 V difference, but it's still way above the min VIH of 0,6 VCC stated in the datasheet for the range VCC = 2.4 - 5.5V

 

-- another pin on port C: checked pin PC2: works fine too, just as PC0 (with or without WDT);

...
if ( PINC & ( 1 << PINC2 ) )	// if ( PINC & ( 1 << PINC0 ) )
...

-- another pin on port B: checked pin PB0: works fine too, just as PC0 & PC2 (with or without WDT)

...
if ( PINB & ( 1 << PINB0 ) )	// if ( PINB & ( 1 << PINB3 ) )
...

 

Last Edited: Wed. Nov 27, 2019 - 10:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, in either case you do not have the WDTON fuse enabled?

 

As there is no WDR in the loop of the

blqsa4ko wrote:
-- program for "WDT on":
then there will be watchdog resets periodically.

 

Still, the whole situation is quite confusing.  Have we seen a pictur3e of your setup?  Is that resistor divider only on the "problem" pin? 

 

 

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This may not make any difference, but I would use the wdt.h provided functions. You are somehow under the impression they will not work for the tiny1634, but they do-

https://godbolt.org/z/2MwWAY

It takes care of everything, and you do not need any separate functions. Your wdt code may be just fine, but I would rather use the wdt.h version that does the change protection write even if not needed in 'safety level 1'.

 

 

When debugging, I would also make some indication as in the above example to show when a watchdog reset occurs so you can see whether you are getting watchdog resets for any reason.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-- " So, in either case you do not have the WDTON fuse enabled? " --> TRUE

WDTON fuse was never enabled. I switch on the watchdog by means of the software, e.g. case "Safety Level 1" as described in Table 8-3 on page 43 of the ATtiny1634 datasheet, and as described by the 1st bullet "Safety Level 1" of paragraph 8.4.1 Timed Sequences for Changing the Configuration of the Watchdog Timer: "In this mode, the Watchdog Timer is initially disabled, but can be enabled by writing the WDE bit to one without any restriction."

 

-- " As there is no WDR in the loop of the -- program for "WDT on": then there will be watchdog resets periodically " --> TRUE

When omitting the "wdt_reset();" at the end of the endless loop the resets are there indeed, ca. every 2 sec as expected by the WDP bits setting; I commented out (omitted) the "wdt_reset();" instruction at the end of the endless loop intentionally in order to see (visually make sure) that the WDT is on and working during program execution, e.g. when I connect the respective pin to +V and keep the line HIGH, the LED keeps being lit and only interrupts shortly ca. every 2 sec when the WDT resets (as expected). If I add the "wdt_reset();" instruction at the end of the endless loop, then there are no resets (LED light also never gets interrupted, also checked this by means of UART), but this does not change anything about the issue that PB3 does not read HIGH level as input when the WDT is off and not enabled at all.

 

-- " the whole situation is quite confusing " --> TRUE, I totally agree with you here, it's also the reason I opened the thread in the forum, and it's now 2 weeks me not being able to spot the problem

 

-- "pictur3e of your setup " --> attached as PDF

 

-- " Is that resistor divider only on the "problem" pin? " --> NO, I used the 10K/1K resistor combination when testing all pins (PB0, PB3, PC0, PC2)

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have not read in detail the entire thread, but would you be willing to try addng the following, without the WD enabled?

    _PROTECTED_WRITE(OSC32KCTRLA, 0x02);

 

I wonder if somehow the function is tied to having the internal 32K clock running (which use of WDT enables).

 

Are there other configurations implied by enabling the WD?  Interrupts enabled?

 

Edit: oops, I have the wrong chip but thinking is the same.  Are there configuration changed implied by enabling the WD?

Last Edited: Wed. Nov 27, 2019 - 03:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try performing both experiments with the same object code.

Toggle watchdog activation every 20 seconds.

One ISR should turn an LED on, the other should turn it off.

The main loop should look something like this:

for(int wflag=0; ; wflag= !wflag) {
    if(wflag) activate_watchdog();
    else      disable_watchdog();

    for(long j=0; j< SECONDS20; ++j) {
        if(watchdog_enabled_bit) light_its_LED();
        else                      dark_its_LED();
        reset_wdt();  // unconditional
    }  // j
}  // wflag

SECONDS20 can be determined from experiment.

Iluvatar is the better part of Valar.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You may want to read the Errata chapter (31) in the datasheet- it seems to explain it all.

 

Not sure why it took this long to get there. I didn't realize they put the errata inside the datasheet and was looking for a separate  document. Live and learn.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
You may want to read the Errata chapter (31) in the datasheet- it seems to explain it all.

Good one, curt.  I was thinking "ISP pins" but that would not be PB3 on this model.

I guess MattRW was on the same track?

===================

I hate "unexplained" puzzles.  Once the cause is found, life can proceed normally.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wow ! I read part of the datasheet several times and plenty of other stuff on the internet, but I confess I never thought about looking up the errata section ... So, my fault :(  Thanks for pinpointing it, curtvm, and thanks for doing my job :-) and many thanks to the others that stood by my thread and put the effort and time to provide hints and help !

Last Edited: Thu. Nov 28, 2019 - 01:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


To save anyone else having to go and look it up, they are talking about...