Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Counter TCNT3 of Timer3 is not defined #57

Closed
dbuezas opened this issue Oct 11, 2020 · 16 comments
Closed

Counter TCNT3 of Timer3 is not defined #57

dbuezas opened this issue Oct 11, 2020 · 16 comments

Comments

@dbuezas
Copy link
Owner

dbuezas commented Oct 11, 2020

The core has the low and high bytes declared, but not the 16 bit uint, which e.g. the Timer1 counterpart has (TCNT1)

#define TCNT3L	_SFR_MEM8(0x94)
#define TCNT3H	_SFR_MEM8(0x95)

Defining it as #define TCNT3 _SFR_MEM16(0x94) works fine for me. Anything I'm missing?

@dbuezas dbuezas changed the title Counter 3 TCNT3 is not defined Counter TCNT3 of Timer3 is not defined Oct 11, 2020
@LaZsolt
Copy link
Collaborator

LaZsolt commented Oct 12, 2020

ADT0 - Auto-monitoring underflow threshold register pair
#define ADT0 _SFR_MEM16(0xA5)

ADT1 - Auto-monitoring overflow threshold register pair
#define ADT1 _SFR_MEM16(0xAA)

OCR3C - TC3 output compare register C ( defined, but not with _SFR_MEM16 )
#define OCR3C _SFR_MEM16(0x9E)

DTR3 - TC3 dead time register
#define DTR3 _SFR_MEM16(0x9C)

DTR3 - TC3 dead time register low and high defined as wrong. Better definiton is:
#define DTR3L _SFR_MEM8(0x9C)
#define DTR3H _SFR_MEM8(0x9D)

OCR3B - TC3 output compare register B ( defined, but not with _SFR_MEM16 )
#define OCR3B _SFR_MEM16(0x9A)

OCR3A - TC3 output compare register A ( defined, but not with _SFR_MEM16 )
#define OCR3A _SFR_MEM16(0x98)

ICR3 - TC3 capture register
#define ICR3 _SFR_MEM16(0x96)

DTR1 - TC1 dead time register
#define DTR1 _SFR_MEM16(0x8C)

DTR1 register is present in LGT8F328D too, so file lgtx8e.h must be edited.

@dbuezas
Copy link
Owner Author

dbuezas commented Oct 14, 2020

OCR3A - TC3 output compare register A ( defined, but not with _SFR_MEM16 )
#define OCR3A _SFR_MEM16(0x98)

Now it finally makes sense! This was driving me crazy, that I couldn't count beyond 255 in CTC mode using OCR3A as TOP. It is defined as a char currently.

@LaZsolt
Copy link
Collaborator

LaZsolt commented Oct 27, 2020

I found an issue. Weird but true.
When accesssing a 16-bit register and an interrupt occured between reading low and high bytes and interrupt routine is accessing another 16-bit register, then high byte lock will be cleared.
eg. a timer interrupt occured in the middle of ADCread. So recommended to disable interrupt while accessing 16-bit registers.

@maxint-rd
Copy link

@LaZsolt - while reading documentation of Timer3 I saw that writing/reading a register may require specific order. E.g. "If write to 16-bit TCNT3, must write TCNT3H firstly. If read 16-bit TCNT3, must read TCNT3L first." Perhaps that's linked to your issue?

Something else - Just in case you ever want to support analogWrite for PWM using Timer 3:
While adding Timer3 support to my FastPwmPin library I had some troubles getting the pin output working on my QFP32 board. After days of reading documentation, much trying and testing I finally found it. If you want to use any PORTF pin for output, you first need to disable the shared pin on the other port. So for OC3B to work on pin PD2, DDRD:2 needs to be set low (input) and DDRF:2 needs to be set high (output).

@LaZsolt
Copy link
Collaborator

LaZsolt commented Jan 12, 2021

@maxint-rd
All 16-bit register read or write operations using the same temporary register for the high byte lock. So care must be taken that there will be no other 16-bit read or write operation in an interrupt, or interrupt must be disabled at a 16-bit register access.
A 16-bit register read or write require a specific order, but C++ compiler for AVR MCUs will handle this order. uint16_t tc3result = TCNT3;
But in the actual release of LGT8Fx package has no appropriate definition of TCNT3 or any LGT specific 16-bit register. You need to correct your copy of lgtx8p.h file.

@maxint-rd
Copy link

maxint-rd commented Jan 12, 2021

@LaZsolt - thank you for the swift reply. Good to know how to deal with 16-bit registers in an interrupt.

I already fixed my copy of the .h file after your comment in another issue's thread. Thanks. Although it did get me to compile my code and have Timer3 running, at first the pin output wouldn't budge. Only after reading somewhere that OC3B was actually on PF2 instead of PD2, I found out I had to first disable PD2 and set PF2 as output to get my fast PWM output to work on pin 2. So I have it working now! (hooray).
BTW: While testing fast PWM on pin 1 (PF1), I also managed to temporarily brick my QFP32 board! Apparently the Holtec USB chip didn't like having 4MHz generated on TX. Fortunately a small cap between pin 1 and 3v3 helped to make the USB recognizable again so then I could flash it...

@LaZsolt
Copy link
Collaborator

LaZsolt commented Jan 12, 2021

I'm glad I was able to help.
Anyway, not easy to handle the LGT's unusual pin sharing. I'm using SPI ethernet module in my project, and it wasn't easy to find out how it is work in the SSOP20 chip.

@dbuezas
Copy link
Owner Author

dbuezas commented May 23, 2021

Just faced another "quirk".
The OCRnx registers (e.g OCR3A) can only be set to a value > 255 AFTER configuring the WGM bits. Otherwise the high bit is blocked to zero. I guess This is not different in atmega328p but it took me a while to find out why my timings were out of whack

@LaZsolt
Copy link
Collaborator

LaZsolt commented May 24, 2021

The OCRnx registers (e.g OCR3A) can only be set to a value > 255 AFTER configuring the WGM bits.

I think it's not an error, but in the databook wasn't mentioned this kind of behaviour.
If OCRnA or OCRnB was written before setting of WGM bits, then the OCRn high byte may be cleared during writing of WGM bits.

In my undertanding the reason is maybe that the WGM bits 2 and 3 are not in the same register than bits 0 and 1. Between writing TCCRnA and TCCRnB maybe there a short time when WGM bits sets the fast PWM 8-bit mode which means the upper bytes of OCRnx registers will be cleared.

kép

@LaZsolt
Copy link
Collaborator

LaZsolt commented May 24, 2021

but in the databook wasn't mentioned this kind of behaviour.

Still, the manual writes something:
"Note that when using fixed TOP values the unused bits are masked to zero when any of the OCR1x registers are written."

@dbuezas
Copy link
Owner Author

dbuezas commented May 24, 2021

Oh wow! I didn't see that!
What is that datasheet you use? I'm still using the orange one with the broken english.

By the way, I noticed 2 differences between lgt328p and atmega328p timers:

  1. In timer1, FPWM, toggle on compare match is only allowed with WGM1=15 (atmega allows it also with WGM1=14)
  2. In all timers, with FPWM, if COMnX is set to do set or clear, LGT "resets" at MAX, whereas ATM resets at BOTTOM (according to the datasheets).

I'm making a tool to configure and visualise timers so I guess I'll put that to the test soon (I want it to match reality after all hehe)

@LaZsolt
Copy link
Collaborator

LaZsolt commented May 24, 2021

What is that datasheet you use?

The quoted text from "ATmega328_P AVR MCU with picoPower Technology Data Sheet"

@dwillmore
Copy link
Collaborator

This issue can be closed and still serve as a reference for others later.

@Novin000
Copy link

Hello to all friends I'm having trouble reading tcnt3 on the atmega64 micro and it's not giving me the correct value
We did all the codes that could be used, but the main problem is that it finds the value of TCNT3L, but the value of TCNT3H gives zero. Examples of the codes I wrote For example this code
uint16_t timer3_value = (TCNT3H << 8) | TCNT3L;​
T3=TCNT3;
TCNT3 =0;
Or
tcnt3 = (T3H*256)+T3L;
T3=TCNT3;
TCNT3 =0;
Or
T3= TCNT3H
8>>T3;
TCNT3 =t3+TCNT3L
When you come to zero TCNT3 or TCNT3H and TCNT3L, it's as if the low value is read and the high value is 0. When you change the frequency, it only shows the correct value of TCNT3L

@dbuezas
Copy link
Owner Author

dbuezas commented Jan 26, 2024

You probably have the timer configured so that the top value is 255.
The tool doesn't specifically support the atmega64, but this may help you figure out where the problem may lie: https://dbuezas.github.io/arduino-web-timers/#mcu=LGT8F328P&timer=3&topValue=0x00FF&CompareOutputModeA=clear-on-match%2C+set-at-max&OCR3A=85

@Novin000
Copy link

Novin000 commented Jan 27, 2024

Thanks mate, I'll check it out
Of course, I work with Codevision

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants