Trying to run Arduino on an ATmega32M1. Compiles, uploads, but doesn't run.

I'm developing a board with an ATmega32M1 (http://www.mouser.com/ds/2/36/doc8209-242488.pdf) for automotive applications. I would like to use the familiar Arduino IDE to program it, but have had to modify some files to work with the ATmega32M1. Right now I can compile the simple "Blink" sketch without errors and upload it to the ATmega32M1. Although the code uploads without errors, the chip does not seem to be responding or "blinking" any of the pins tried.

Chip: ATmega32M1
Programmer: Arduino as ISP
OS: Windows XP Home
Arduino IDE: 1.0.4

Files modified:

  1. Board.txt------Added "Atmega32M1" section.
  2. Wiring_private.h-----Added additional interrupts
  3. Wrote a pins_arduino.h-----Tried to account for and accommodate all pins to be used. this file was then placed in its own folder under "hardware/arduino/variants"

Board.txt addition: (bootloader is not being used)

atmega32m1.name=ATmega32M1 (arduino)

atmega32m1.upload.protocol=arduino
atmega32m1.upload.maximum_size=30720
atmega32m1.upload.speed=19200

atmega32m1.bootloader.low_fuses=0xE2
atmega32m1.bootloader.high_fuses=0xD9
atmega32m1.bootloader.extended_fuses=0xD9
atmega32m1.bootloader.path=atmega
atmega32m1.bootloader.file=ATmegaBOOT_168_atmega328.hex
atmega32m1.bootloader.unlock_bits=0x3F
atmega32m1.bootloader.lock_bits=0x0F

atmega32m1.build.mcu=atmega32m1
atmega32m1.build.f_cpu=8000000L
atmega32m1.build.core=arduino
atmega32m1.build.variant=standard

Wiring_private.h (hardware/arduino/cores/arduino/wiring_private.h) now looks like this:

#ifndef WiringPrivate_h
#define WiringPrivate_h

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdarg.h>

#include "Arduino.h"

#ifdef __cplusplus
extern "C"{
#endif

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define EXTERNAL_INT_0 0
#define EXTERNAL_INT_1 1
#define EXTERNAL_INT_2 2
#define EXTERNAL_INT_3 3
#define EXTERNAL_INT_4 4
#define EXTERNAL_INT_5 5
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
#define EXTERNAL_INT_8 8
#define EXTERNAL_INT_9 9
#define EXTERNAL_INT_10 10
#define EXTERNAL_INT_11 11
#define EXTERNAL_INT_12 12
#define EXTERNAL_INT_13 13
#define EXTERNAL_INT_14 14
#define EXTERNAL_INT_15 15
#define EXTERNAL_INT_16 16
#define EXTERNAL_INT_17 17
#define EXTERNAL_INT_18 18
#define EXTERNAL_INT_19 19
#define EXTERNAL_INT_20 20
#define EXTERNAL_INT_21 21
#define EXTERNAL_INT_22 22
#define EXTERNAL_INT_23 23

#if defined(__AVR_ATMEGA32M1__)
#define EXTERNAL_NUM_INTERRUPTS 24
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
#define EXTERNAL_NUM_INTERRUPTS 3
#elif defined(__AVR_ATmega32U4__)
#define EXTERNAL_NUM_INTERRUPTS 4
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif

typedef void (*voidFuncPtr)(void);

#ifdef __cplusplus
} // extern "C"
#endif

#endif

Notes:

  1. Power is definitely getting to the board. On board power LED is lit and voltages checked with multimeter.
  2. All lines have been checked with multimeter.
  3. Arduino IDE shows good upload.
    a. Avrdude knows that it is programming an ATmega32M1 (from verbose output):
         AVR Part                      : ATMEGA32M1
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PE2
         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                 :

b. ATmega32M1's signature is properly recognized (from verbose output):

avrdude: AVR device initialized and ready to accept instructions

Reading | avrdude: Send: u [75]   [20] 
avrdude: Recv: . [14] . [1e] . [95] . [84] . [10] 
################################################## | 100% 0.03s

avrdude: Device signature = 0x1e9584

c. Appropriate thank you is given at the end (from verbose output):

avrdude: Recv: . [14] 
avrdude: Recv: . [10] 
### | 100% 1.38s

avrdude: 1074 bytes of flash written
avrdude: Send: Q [51]   [20] 
avrdude: Recv: . [14] 
avrdude: Recv: . [10] 

avrdude done.  Thank you.
  1. Since no bootloader has been used yet, no crystal has been added to the board yet and it is running off the internal resonator.
  2. Board is a custom board of my own design.
  3. Right now I'm just trying a simple "Blink" sketch, but if I add "Serial.begin(9600);" the compiler throws an error:
error: 'Serial' was not declared in this scope

Although it is not my intention to use Serial yet, I wanted to add that note as it might be a clue!

Thank you in advance for your time with this. I look forward to your thoughts and suggestions.
(Due to the length of this post I'm splitting it up and adding the coding in the following post.)

Pins_arduino.h is like this:

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <avr/pgmspace.h>

#define NUM_DIGITAL_PINS            22
#define NUM_ANALOG_INPUTS           10

#define analogInputToDigitalPin(p)  (((p) < 8) ? (p) + 14 : ((((p)==8) ? (p) -8) : ((((p)==9) ? (p) +4) : -1)))

#if defined(__AVR_ATmega8__)
#define digitalPinHasPWM(p)         ((p) == 9 || (p) == 10 || (p) == 11)
#else
#define digitalPinHasPWM(p)         ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11) //(p) // They all do! 
#endif

static const uint8_t SS   = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK  = 13;

//Atmega32m1 has no I2C capabilities
//static const uint8_t SDA = 18;
//static const uint8_t SCL = 19;
static const uint8_t LED_BUILTIN = 9;

static const uint8_t A0 = 14;
static const uint8_t A1 = 15;
static const uint8_t A2 = 16;
static const uint8_t A3 = 17;
static const uint8_t A4 = 18;
static const uint8_t A5 = 19;
static const uint8_t A6 = 20;
static const uint8_t A7 = 21;
// Added two more analog inputs for the ATmega32m1
static const uint8_t A8 = 0;
static const uint8_t A9 = 13;



#define digitalPinToPCICR(p)    (((p) >= 0 && (p) <= 22) ? (&PCICR) : ((uint8_t *)0))

#define digitalPinToPCICRbit(p) ( ((p) >= 2 && (p) <=3)  || \
                                  ((p) >=11 && (p) <=13) || \
                                  ((p) >=16 && (p) <=18) ? 0 : \
                                ( ((p) >= 4 && (p) <=5)  || \
                                  ((p) >=19 && (p) <=21) ? 1 : \
                                2))
#define digitalPinToPCMSK(p)    ( ((p) >= 2 && (p) <=3)  || \
                                  ((p) >=11 && (p) <=13) || \
                                  ((p) >=16 && (p) <=18) ? (&PCMSK0) : \
                                ( ((p) >= 4 && (p) <=5)  || \
                                  ((p) >=19 && (p) <=21) ? (&PCMSK1) : \
                                (&PCMSK2)))
//#define digitalPinToPCMSK(p)    (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
//#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
#define digitalPinToPCMSKbit(p) ( ((p) == 4 || (p) == 6 || (p) == 12 ) ? 0 : \
                                ( ((p) == 5 || (p) == 9 || (p) == 11 ) ? 1 : \
                                ( ((p) == 7 || (p) == 16 )             ? 2 : \
                                ( ((p) == 1 || (p) == 2 )              ? 3 : \
                                ( ((p) == 0 || (p) == 3  || (p) == 19) ? 4 : \
                                ( ((p) == 14 ||(p) == 17 || (p) == 20) ? 5 : \
                                ( ((p) == 15 ||(p) == 18 || (p) == 21) ? 6 : \
                                7)))))))


#ifdef ARDUINO_MAIN

// On the Arduino board, digital pins are also used
// for the analog output (software PWM).  Analog input
// pins are a separate set.

// ATMEL ATMEGA8 & 168 / ARDUINO
//
//                  +-\/-+
//            PC6  1|    |28  PC5 (AI 5)
//      (D 0) PD0  2|    |27  PC4 (AI 4)
//      (D 1) PD1  3|    |26  PC3 (AI 3)
//      (D 2) PD2  4|    |25  PC2 (AI 2)
// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
//      (D 4) PD4  6|    |23  PC0 (AI 0)
//            VCC  7|    |22  GND
//            GND  8|    |21  AREF
//            PB6  9|    |20  AVCC
//            PB7 10|    |19  PB5 (D 13)
// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
//      (D 8) PB0 14|    |15  PB1 (D 9) PWM
//                  +----+
//
// (PWM+ indicates the additional PWM pins on the ATmega168.)

// ATMEL ATMEGA1280 / ARDUINO
//
// 0-7 PE0-PE7   works
// 8-13 PB0-PB5  works
// 14-21 PA0-PA7 works 
// 22-29 PH0-PH7 works
// 30-35 PG5-PG0 works
// 36-43 PC7-PC0 works
// 44-51 PJ7-PJ0 works
// 52-59 PL7-PL0 works
// 60-67 PD7-PD0 works
// A0-A7 PF0-PF7
// A8-A15 PK0-PK7


// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	(uint16_t) &DDRB,
	(uint16_t) &DDRC,
	(uint16_t) &DDRD,
	//Added PortE for Atmega32M1
	(uint16_t) &DDRE,
};

const uint16_t PROGMEM port_to_output_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	(uint16_t) &PORTB,
	(uint16_t) &PORTC,
	(uint16_t) &PORTD,
	//Added PortE for Atmega32M1
	(uint16_t) &PORTE,	
};

const uint16_t PROGMEM port_to_input_PGM[] = {
	NOT_A_PORT,
	NOT_A_PORT,
	(uint16_t) &PINB,
	(uint16_t) &PINC,
	(uint16_t) &PIND,
	//Added PortE for Atmega32M1
	(uint16_t) &PINE,
};

const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
	PD, // D0 - PD4 - RX - A8
	PD, // D1 - PD3 - TX
	PB, // D2 - PB3
	PB, // D3 - PB4
	PC, // D4 - PC0
	PC, // D5 - PC1
	PD, // D6 - PD0
	PD, // D7 - PD2
	
	PC, // D8 - PC7
	PD, // D9 - PD1 - LED_BUILTIN
	PD, // D10 - PD7 - SS
	PB, // D11 - PB1 - MOSI
	PB, // D12 - PB0 - MISO
	PB, // D13 - PB7 - SCK - A9
	PD, // D14 - PD5 - A0
	PD, // D15 - PD6 - A1
	
	PB, // D16 - PB2 - A2
	PB, // D17 - PB5 - A3
	PB, // D18 - PB6 - A4
	PC, // D19 - PC4 - A5
	PC, // D20 - PC5 - A6
	PC, // D21 - PC6 - A7
	PC, // D22 - PC7
	PE, // D23 - PE0
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
	_BV(4), /* 0 */
	_BV(3),
	_BV(3),
	_BV(4),
	_BV(0),
	_BV(1),
	_BV(0),
	_BV(2),
	
	_BV(7), /* 8 */
	_BV(1),
	_BV(7),
	_BV(1),
	_BV(0),
	_BV(7),
	_BV(5), 
	_BV(6),
	
	_BV(2), /* 16 */
	_BV(5),
	_BV(6),
	_BV(4),
	_BV(5),
	_BV(6),
	_BV(7),
	_BV(0),
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
	NOT_ON_TIMER,
	TIMER0A,
	NOT_ON_TIMER,
	NOT_ON_TIMER,	
	NOT_ON_TIMER,
	TIMER1B,
	NOT_ON_TIMER,
	TIMER1A,
  
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,	
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,

	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,	
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
	NOT_ON_TIMER,
  	

};

#endif

#endif

I've now tried making a whole new folder and core just for the ATmega32m1 as suggested at avr-developers.com. I did this with a clean install of Arduino IDE 1.0.5. Still the same result: compiles without error, uploads without error, but then doesn't seem to run the sketch.

"The sketch"? What sketch?

Thank you for your question, Coding Badly. As I mentioned in the first post, the sketch is the standard "Blink" sketch. I will include it below:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 9;  // Pin LED is connected to on my ATmega32M1 board

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Just to be sure, I've checked all of the pins several times to see if I had messed up the pin assignment some how and maybe it was "blinking" a different pin.

Have you changed the fuses from the default? If not, be aware that the CLKDIV8 fuse is programmed by default, and will divide your clock frequency down to 1 MHz instead of 8 MHz you have in your Boards.txt. This means that your LED will change state every 8 seconds instead of every second. When checking the pins, have you waiting long enough to be sure 8 seconds have gone by for each pin?

Jiggy-Ninja, I did try atmega32m1.build.f_cpu=1000000L, but had tried atmega32m1.build.f_cpu=8000000L, just to be sure. You are correct though that it should work with the default 1MHz.

Just to make sure that I wasn't missing the blinking part as you mentioned I have been running the sketch with most of the loop section commented out like this:

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  //delay(1000);               // wait for a second
  //digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  //delay(1000);               // wait for a second
}

Keep the ideas coming, guys. I appreciate you taking the time to look over this!

atmega32m1.build.variant=standard

This might be what's causing you problems. You said you put the pins_arduino.h in its own variant folder, but you aren't specifying that variant in boards.txt. Change "standard" to whatever you named the variant folder and check it again.

Jiggy-Ninja, yes, I've tried it with:

atmega32m1.build.variant=atmega32m1

since that is the name of the folder under variant. Before I posted the code, I had tried it with "standard" again hoping that even if the pin assignment was wrong with the "standard" pins_arduino.h file that at least one pin some where on the chip would show signs of going HIGH! :slight_smile:

Turn your .elf file into a listing, and post that somewhere?

#include <util/delay.h>

void setup( void )
{
  DDRB |= (1 << DDB1);
}

void loop( void )
{
  if ( PINB & (1 << PINB1) )
  {
    PORTB &= ~ (1 << PORTB1); 
  }
  else
  {
    PORTB |= (1 << PORTB1); 
  }
  _delay_ms( 1000 );
}

Blink? No blink?

Damn, CB beat me to what I was going to do. >.< Oh well, I still have a contribution regarding Serial.

#if defined(UBRRH) || defined(UBRR0H)
  extern HardwareSerial Serial;
#elif defined(USBCON)
  #include "USBAPI.h"
//  extern HardwareSerial Serial_;  
#endif
#if defined(UBRR1H)
  extern HardwareSerial Serial1;
#endif
#if defined(UBRR2H)
  extern HardwareSerial Serial2;
#endif
#if defined(UBRR3H)
  extern HardwareSerial Serial3;
#endif

This is from HardwareSerial.h. The problem is that none of the idef'ed registers are present on a mega32m1. Instead you have a LIN / UART controller with names line LINBRR instead of UBRR. HardwareSerial is another thing you're going to have to modify.

Coding Badly, thanks for the suggestion concerning manipulating the pins directly via the registers. I too had tried something similar, but my code wasn't a efficient as yours! :slight_smile: I tried it exactly like you posted (copy and pasted it). It compiled and uploaded without a hitch, but no blink. I then altered it to DDRD, DDD1, PIND, PORTD & PORTD1, just to try a different pin. Same result.

Jiggy-Ninja, I greatly appreciate your contributions as well. :slight_smile: Thanks for the heads up concerning the HardwareSerial.h file. I had not caught that. I will definitely look into it and adapt. Thank you very much.

westfw, I had never looked up an .elf file before, but I've attached the latest .elf file from trying Coding Badly's code.

sketch_sep05a.cpp.elf (9.55 KB)

RaMansell:
...but no blink...

That leaves two possibilities. This will eliminate one...

#include <util/delay.h>

int main( void )
{
  DDRB |= (1 << DDB1);
  
  while ( true )
  {
    if ( PINB & (1 << PINB1) )
    {
      PORTB &= ~ (1 << PORTB1); 
    }
    else
    {
      PORTB |= (1 << PORTB1); 
    }
    _delay_ms( 1000 );
  }
  return( 0 );
}

Okay, Coding Badly, I just tried your latest suggestion, coping and pasting the code with the "int main void" in it. Same as before: compiles and uploads without error, but no blink. :frowning:

PD, // D9 - PD1 - LED_BUILTIN // your pins_arduino.h
:
DDRB |= (1 << DDB1); // Crossroad's code

So which pin are you actually looking at? Give us a package type and an actual pin number, please, so that we can work backward.
(similarly "here's a elf of Crossroads code; I previously checked other pins and they weren't toggling either" is ... vague. It would be better to have an exact combination of source/object/pin-looked-at that didn't work.)

Hmm. Are you sure that you have a 32m1? I see (and am surprised) that the atmega32m1 is not-at-all like an atmega32a (grr.)
(it is, however, similar to the 328p.)

RaMansell:
...but no blink...

Are you uploading via bootloader?

Did you wait about 30 seconds in case the clock is slower than you expect?

Are you certain the LED is connected to pin B1?

Coding Badly, I am not using a bootloader but just using a RedBoard (Uno) from Sparkfun.com as an Arduino ISP. If you know of a bootloader for the ATmega32M1, please let me know! :slight_smile:

I have tried waiting several seconds for each pin tested. I've also tried deleting the delays and taking out the part of the "Blink" sketch that sets the pin "LOW." This way, I'm just setting the pin (whichever one I'm testing for) to be "HIGH."

I'm certain that the LED on my custom board (see pictures attached in next post) is attached to pin PD1 (referred to as pin #9 in my "pins_arduino.h" file). I've also tried pin PB1, because that is the pin used in your code.

Whether running your test code, or my test code, upon uploading any sketch, I check every physical pin with an LED and test lead to see if I'm accidentally setting a different physical pin "HIGH!"