0

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:

-enter image description here

same picture with more measurement information:

enter image description here

2
  • 2
    So 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 1
    – chrisl
    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... Nov 29, 2022 at 9:09

2 Answers 2

3

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.

3
  • 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 time 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. Nov 30, 2022 at 8:12
  • thank you, I will study more about vports then, very helpful! Nov 30, 2022 at 10:32
1

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.

3
  • The code writes to an “output toggle” register, which is more efficient than doing the read-modify-write sequence entirely in software. 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 :/ 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. Nov 30, 2022 at 8:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.