system delay functions are not producing the correct timings

181 views Asked by At

If anyone can help me with this problem I would be very grateful.
Here's what i know.

I have a custom PCB based around an atmega328p processor.
I am using atmelstudio 7.0.1645 IDE.
I have used the ASF wizard to set up my project.
I am programming using a USBTinyISP.

In my main loop I am toggling an LED and delaying 1 second.
Yet when i check on a scope the LED flashes at a rate of 1.6s

I have checked the fuses and all are set correctly as default (E=0xff, H=0xD9, L=0x62) this should give a 1MHz clock. (8MHz internal RC plus divide by 8 prescaler)

I am using the ASF's System Clock Control Service and the Delay Routines Service.

calling sysclk_get_main_hz(); returns 16000000.
calling sysclk_get_source_clock_hz(); returns 1000000.
calling sysclk_get_cpu_hz(); returns 1000000.
Which all seems correct to me.

Also if i compile and program a similar project from arduino ide the delay functions are spot on so I feel i can rule out any obvious hardware issues. I am just using the internal RC anyway.

I have trauled goodle for similar problems but just get the usual Clock setup problems that i feel I have exhausted.

Any extra help would be very much appreciated. Thanks.

main.c

/**
 * \file
 *
 * \brief Empty user application template
 *
 */

/**
 * \mainpage User Application template doxygen documentation
 *
 * \par Empty user application template
 *
 * Bare minimum empty user application template
 *
 * \par Content
 *
 * -# Include the ASF header files (through asf.h)
 * -# "Insert system clock initialization code here" comment
 * -# Minimal main function that starts with a call to board_init()
 * -# "Insert application code here" comment
 *
 */

/*
 * Include header files for all drivers that have been imported from
 * Atmel Software Framework (ASF).
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include <asf.h>

uint32_t main_hz = 0;
uint32_t source_clock_hz = 0;
uint32_t cpu_hz = 0;

int main (void)
{
    sysclk_init();
    board_init();

    /* Insert application code here, after the board has been initialized. */

    main_hz = sysclk_get_main_hz();
    source_clock_hz = sysclk_get_source_clock_hz();
    cpu_hz = sysclk_get_cpu_hz();

    while(1){
        ioport_toggle_pin(LED_STRIP);
        delay_ms(1000);
    }
}

conf_clock.h

/**
 * \file
 *
 * \brief Chip-specific system clock manager configuration
 *
 * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
 *
 * \asf_license_start
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel microcontroller product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \asf_license_stop
 *
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#ifndef CONF_CLOCK_H_INCLUDED
#define CONF_CLOCK_H_INCLUDED

/* ===== System Clock Source Options */
#define SYSCLK_SRC_RC16MHZ    0
#define SYSCLK_SRC_RC128KHZ   1
#define SYSCLK_SRC_TRS16MHZ   2
#define SYSCLK_SRC_RC32KHZ    3
#define SYSCLK_SRC_XOC16MHZ   4
#define SYSCLK_SRC_EXTERNAL   5

/* =====  Select connected clock source */
#define  SYSCLK_SOURCE         SYSCLK_SRC_RC16MHZ
/* #define SYSCLK_SOURCE        SYSCLK_SRC_RC128KHZ */
/* #define SYSCLK_SOURCE        SYSCLK_SRC_TRS16MHZ */
/* #define SYSCLK_SOURCE        SYSCLK_SRC_XOC16MHZ */

/* ===== System Clock Bus Division Options */
#define CONFIG_SYSCLK_PSDIV         SYSCLK_PSDIV_8

#endif /* CONF_CLOCK_H_INCLUDED */

AVRDude Output

avrdude.exe: Version 6.3, compiled on Feb 17 2016 at 09:25:53
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2014 Joerg Wunsch

             System wide configuration file is "C:\Program Files (x86)\AVRDude\avrdude.conf"

             Using Port                    : usb
             Using Programmer              : usbtiny
avrdude.exe: usbdev_open(): Found USBtinyISP, bus:device: bus-0:\\.\libusb0-0001--0x1781-0x0c9f
             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

             Programmer Type : USBtiny
             Description     : USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/
avrdude.exe: programmer operation not supported

avrdude.exe: Using SCK period of 10 usec
CMD: [ac 53 00 00] [ff fe 53 00]
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | CMD: [30 00 00 00] [00 30 00 1e]
CMD: [30 00 01 00] [00 30 00 95]
################CMD: [30 00 02 00] [00 30 00 0f]
################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 1, lfuse value: 62
CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 2, lfuse value: 62
CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 3, lfuse value: 62
avrdude.exe: safemode: lfuse reads as 62
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 1, hfuse value: d9
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 2, hfuse value: d9
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 3, hfuse value: d9
avrdude.exe: safemode: hfuse reads as D9
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 1, efuse value: ff
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 2, efuse value: ff
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 3, efuse value: ff
avrdude.exe: safemode: efuse reads as FF
avrdude.exe: NOTE: "flash" memory has been specified, an erase cycle will be performed
             To disable this feature, specify the -D option.
avrdude.exe: erasing chip
CMD: [ac 80 00 00] [00 ac 80 00]
avrdude.exe: Using SCK period of 10 usec
CMD: [ac 53 00 00] [00 ac 53 00]
avrdude.exe: reading input file "\Atmel Studio\7.0\GccBoardProject2\GccBoardProject2\Debug\GccBoardProject2.hex"
avrdude.exe: writing flash (228 bytes):

Writing | CMD: [4c 00 00 00] [92 4c 00 00]
#########################CMD: [4c 00 40 00] [ff 4c 00 40]
######################### | 100% 0.32s

avrdude.exe: 228 bytes of flash written
avrdude.exe: verifying flash memory against \Atmel Studio\7.0\GccBoardProject2\GccBoardProject2\Debug\GccBoardProject2.hex:
avrdude.exe: load data flash data from input file \Atmel Studio\7.0\GccBoardProject2\GccBoardProject2\Debug\GccBoardProject2.hex:
avrdude.exe: input file \Atmel Studio\7.0\GccBoardProject2\GccBoardProject2\Debug\GccBoardProject2.hex contains 228 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 0.25s

avrdude.exe: avr_read(): skipping page 2: no interesting data
avrdude.exe: avr_read(): skipping page 3: no interesting data
avrdude.exe: avr_read(): skipping page 4: no interesting data
...
...
avrdude.exe: avr_read(): skipping page 254: no interesting data
avrdude.exe: avr_read(): skipping page 255: no interesting data
avrdude.exe: verifying ...
avrdude.exe: 228 bytes of flash verified
avrdude.exe: reading input file "0xff"
avrdude.exe: writing efuse (1 bytes):

Writing | CMD: [50 08 00 00] [ff 50 08 ff]
################################################## | 100% 0.00s

avrdude.exe: 1 bytes of efuse written
avrdude.exe: verifying efuse memory against 0xff:
avrdude.exe: load data efuse data from input file 0xff:
avrdude.exe: input file 0xff contains 1 bytes
avrdude.exe: reading on-chip efuse data:

Reading | CMD: [50 08 00 00] [00 50 08 ff]
################################################## | 100% 0.00s

avrdude.exe: verifying ...
avrdude.exe: 1 bytes of efuse verified
avrdude.exe: reading input file "0xd9"
avrdude.exe: writing hfuse (1 bytes):

Writing | CMD: [58 08 00 00] [00 58 08 d9]
################################################## | 100% 0.00s

avrdude.exe: 1 bytes of hfuse written
avrdude.exe: verifying hfuse memory against 0xd9:
avrdude.exe: load data hfuse data from input file 0xd9:
avrdude.exe: input file 0xd9 contains 1 bytes
avrdude.exe: reading on-chip hfuse data:

Reading | CMD: [58 08 00 00] [00 58 08 d9]
################################################## | 100% 0.00s

avrdude.exe: verifying ...
avrdude.exe: 1 bytes of hfuse verified
avrdude.exe: reading input file "0x62"
avrdude.exe: writing lfuse (1 bytes):

Writing | CMD: [50 00 00 00] [00 50 00 62]
################################################## | 100% 0.00s

avrdude.exe: 1 bytes of lfuse written
avrdude.exe: verifying lfuse memory against 0x62:
avrdude.exe: load data lfuse data from input file 0x62:
avrdude.exe: input file 0x62 contains 1 bytes
avrdude.exe: reading on-chip lfuse data:

Reading | CMD: [50 00 00 00] [00 50 00 62]
################################################## | 100% 0.00s

avrdude.exe: verifying ...
avrdude.exe: 1 bytes of lfuse verified

CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 1, lfuse value: 62
CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 2, lfuse value: 62
CMD: [50 00 00 00] [00 50 00 62]
avrdude.exe: safemode read 3, lfuse value: 62
avrdude.exe: safemode: lfuse reads as 62
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 1, hfuse value: d9
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 2, hfuse value: d9
CMD: [58 08 00 00] [00 58 08 d9]
avrdude.exe: safemode read 3, hfuse value: d9
avrdude.exe: safemode: hfuse reads as D9
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 1, efuse value: ff
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 2, efuse value: ff
CMD: [50 08 00 00] [00 50 08 ff]
avrdude.exe: safemode read 3, efuse value: ff
avrdude.exe: safemode: efuse reads as FF
avrdude.exe: safemode: Fuses OK (E:FF, H:D9, L:62)
1

There are 1 answers

0
Dimitris Minagias On

I had a similar problem with the timing, so I went to the implementation of sysclk.h and I added manually the correct 16000000UL to the inline function

static inline uint32_t sysclk_get_source_clock_hz(void)
{
    return 16000000UL;
    switch (CONFIG_SYSCLK_PSDIV) {
    case SYSCLK_PSDIV_1: /* Fall through */
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 2;
    } else {
        return sysclk_get_main_hz();
    }

case SYSCLK_PSDIV_2:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 4;
    } else {
        return sysclk_get_main_hz() / 2;
    }

case SYSCLK_PSDIV_4:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 8;
    } else {
        return sysclk_get_main_hz() / 4;
    }

case SYSCLK_PSDIV_8:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 16;
    } else {
        return sysclk_get_main_hz() / 8;
    }

case SYSCLK_PSDIV_16:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 32;
    } else {
        return sysclk_get_main_hz() / 16;
    }

case SYSCLK_PSDIV_32:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 64;
    } else {
        return sysclk_get_main_hz() / 32;
    }

case SYSCLK_PSDIV_64:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 128;
    } else {
        return sysclk_get_main_hz() / 64;
    }

case SYSCLK_PSDIV_128:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 256;
    } else {
        return sysclk_get_main_hz() / 128;
    }

case SYSCLK_PSDIV_256:
    if (SYSCLK_SOURCE == SYSCLK_SRC_RC16MHZ ||
            SYSCLK_SOURCE == SYSCLK_SRC_RC128KHZ) {
        return sysclk_get_main_hz() / 512;
    } else {
        return sysclk_get_main_hz() / 256;
    }

default:
    /*Invalide case*/
    return 0;
}

}