I am programming an attiny202 which as per datasheet can run up to 20Mhz, but after compiling/uploading this simple code to the attiny202 and watch the PA2 pin on the oscilloscope, I see that the pin oscilates at ~2.5MHz which is around 10x slower than I would expect, this is even I disable prescaling, am I missing something? (I am new into programming microcontrollers)
note: VCC is 5V (from lab bench PSU)
main.c
#include <avr/io.h>
int main(void)
{
// no prescaling (if lesss than 4.5V, this is overclocking)
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0);
PORTA_DIR = _BV(2);
while(1)
{
PORTA_OUTTGL = _BV(2);
}
}
Makefile
PRG = main
CC = avr-gcc
MCU_TARGET = attiny202
OPTIMIZE = -Os
OBJCOPY = avr-objcopy
UART = /dev/ttyUSB0
all: $(PRG).elf $(PRG).hex
$(PRG).elf: $(PRG).c » $(CC) -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(PRG).c -o $(PRG).elf
%.hex: %.elf
» $(OBJCOPY) -j .text -j .data -O ihex $< $@
clean:
» rm *.elf *.hex
burn: $(PRG).hex
» pymcuprog -t uart -d $(MCU_TARGET) -u $(UART) write -f $(PRG).hex --erase --verify
bitmaps from oscilloscope:
same picture with more measurement information:
-
2So you are toggling a pin in code and expect it to change at the same frequency as the clock? That won't work, since even such a simple action takes more clock pulses than one. I'm not that much into this to tell you how many cycles are needed, but I'm very sure it is significantly more than 1chrisl– chrisl11/29/2022 09:06:33Commented Nov 29, 2022 at 9:06
-
of course it wont run at same freq as the main clock!, toggling a value into a reg takes more than 1 cycle, I feel dumb, I am sorry, I have not slept much in the last 48 hours out of excitement seeing this working, is my first SOP8!, please, post your answer so I can accept it, going to sleep now before I ask more questions before thinking...Joe Cabezas– Joe Cabezas11/29/2022 09:09:25Commented Nov 29, 2022 at 9:09
2 Answers 2
Just as a complement to chrisl's answer, if you disassemble the compiled program, you should see that your infinite loop looks like this:
1: sts 0x0407, r24 ; write to PORTA_OUTTGL
rjmp 1b ; jump back to previous instruction
These instructions take two cycles each, for a total of four cycles per loop iteration. The loop is thus expected to run at F_CPU÷4 = 5 MHz. Since a cycle of the output waveform takes two toggles, you expect to see 2.5 MHz on the oscilloscope.
You should be able to speed this up by writing to the virtual port
register VPORTA_IN
instead of PORTA_OUTTGL
. Virtual port registers
are equivalent to regular port registers, but they are mapped into the
I/O space of the microcontroller. This allows the compiler to replace
the sts
instruction by the shorter and faster out
instruction. The
loop should then complete in only 3 CPU cycles and output a waveform at
3.33 MHz.
-
oh thanks for this explanation!, why is the advantage then of using just non virtual port if vports are "better"? (of course there is a reason, but I am noob), care to explain?, thank you so much for your timeJoe Cabezas– Joe Cabezas11/29/2022 22:59:59Commented Nov 29, 2022 at 22:59
-
@JoeCabezas: The regular ports have extra functionality: set, clear and toggle register addresses for each underlying register. Also, the address space available for virtual ports is tiny, so most peripherals only have regular ports.Edgar Bonet– Edgar Bonet11/30/2022 08:12:57Commented Nov 30, 2022 at 8:12
-
thank you, I will study more about vports then, very helpful!Joe Cabezas– Joe Cabezas11/30/2022 10:32:41Commented Nov 30, 2022 at 10:32
You are constantly toggling a pin in software. This involves copying the register data to the working register, toggling the bit and writing the result back.
This takes way more than only 1 clock cycle. So the resulting frequency is way lower. With only software you just cannot get near the clock frequency of the microcontroller.
-
The code writes to an "output toggle" register, which is more efficient than doing the read-modify-write sequence entirely in software.Edgar Bonet– Edgar Bonet11/29/2022 10:35:37Commented Nov 29, 2022 at 10:35
-
@EdgarBonet thank you, but still it seems like it takes a lot of cycles enought to reduce from 20MHz to 2.5Mhz, 10 cycles?, I really think I am missing something :/Joe Cabezas– Joe Cabezas11/29/2022 22:58:06Commented Nov 29, 2022 at 22:58
-
1@JoeCabezas: 20 MHz / 2.5 MHz = 8 cycles, not 10. That is two loop iterations (because the output signal is toggled twice) at 4 CPU cycles per iteration. See my answer for the detailed cycle count.Edgar Bonet– Edgar Bonet11/30/2022 08:13:12Commented Nov 30, 2022 at 8:13
Explore related questions
See similar questions with these tags.