ATmega-M1 and alternate SPI

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm planning to use a ATmega-M1 for a switching power supply. The built-in power stage controller PSC is a nice fit. But some of the PSC output pins cohabitate with ISP functions. For example PSCOUT0B is on the same PIN as SCK. As PSCOUT0B is wired to my switching hardware this looks like a bad idea.

Now there seem to be a full set of alternate pins for ISP. There is SCK_A, MOSI_A, etc. The seem to be better placed (not on the same pin as a power-output). But I'm missing a clear understanding how I can choose between the two sets of SPI pins. From the Serial Programming part of the data sheet I have even the impression that the _A pins are to be used for ISP.

A bit confused and looking for clarification

Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've just taken a look at the preliminary datasheet on Atmel's website.

I'm 99.9% sure that ISP is performed on the MOSI_A, MISO_A and SCK_A pins (Table 27-15 on page 293 and Figure 27-10 on page 303).

It seems as though you can use these pins as an alternate SPI port by setting bit SPIPS in MCUCR to 1 (18.5.1 on page 159) but ISP is fixed on the alternate (_A) pins.

Hope this helps.

All the best

Pete

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pstansfeld wrote:
I'm 99.9% sure that ISP is performed on the MOSI_A, MISO_A and SCK_A pins (Table 27-15 on page 293 and Figure 27-10 on page 303).

After scanning the Datasheet for SPIPS I found the following:

15.2.3 MCU Control Register – MCUCR

Quote:
Bit 7– SPIPS: SPI Pin Redirection
Thanks to SPIPS (SPI Pin Select) in MCUCR Sfr, SPI pins can be redirected.

• When the SPIPS bit is written to zero, the SPI signals are directed on pins MISO,MOSI, SCK and SS.
• When the SPIPS bit is written to one,the SPI signals are directed on alternate SPI pins, MISO_A, MOSI_A, SCK_A and SS_A.
Note that programming port are always located on alternate SPI port.


I have to say I find this quite confusing, why has the programming port suddenly become an alternate facility ?

What has the guy been smoking ?

Also, this is quite important, so I would expect this to be said explicitly, not mentioned in a small footnote.

Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What has the guy been smoking ?

Probably so it doesn't interfere with the special purpose(s) of this model, as noted in the OP.

The Serial Programming Pin Mapping section seems pretty clear and unambiguous. The OP is asking about ISP setup. I'll leave the theological discussion on redirecting SPI to those that speak ex cathedra.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
What has the guy been smoking ?

Probably some sort of raw or pickled fish if they're from anywhere near Trondheim. :wink:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just to mention, I'm the smoking OP. My point is: Why rename the good old ISP pins to _A, then introduce alternate pins and name them with the original names ?

However, this is only superficial. Besides this I like the -M1 chip more and more, the longer I read the datasheet. I's got a lot of interesting hardware on board !

Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

markus_b wrote:
Just to mention, I'm the smoking OP. My point is: Why rename the good old ISP pins to _A, then introduce alternate pins and name them with the original names ?
They didn't.
They separated the ISP and normal SPI pins.
As an alternative,
you can move the SPI functionality to the ISP pins,
but not the other way around.

Don't let it bother you too much.
Cf. some of my early posts.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have to admit, I have never used SPI for something else than ISP, so in my mind they are sort of synonymous. As I use mostly ISP for programming this looks to me like a main functionality for SPI. Also in all AVRs I've worked with up until now (mostly smaller ones) ISP and SPI is done on the same pins, reinforcing my perception. Now suddenly seeing my beloved main functionality relegated to alternate seems counterintuitive. I'd at least thought to find a big preemptive remark about this for all us naive people working our way through the data sheet.

Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Also in all AVRs I've worked with up until now (mostly smaller ones) ISP and SPI is done on the same pins, reinforcing my perception.

Few (no?) Tinys have SPI at all. But all but Tiny10 family have ISP.

I don't quite get the objection--the chip designers moved the ISP away from your critical alternate function thus avoiding you problems.

Quote:

I'd at least thought to find a big preemptive remark about this for all us naive people working our way through the data sheet.

AFAIK every AVR model has a datasheet section that is in the "bookmarks" of the PDF -- "Serial Programming Pin mapping".

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lee, you let me any chance to save some face :-). I was caught with foot in mouth alright.

In my narrow and tiny-ladened AVR view ISP=SPI, the letters are the same and the pins have the same name, too. Probably have to grow up to these 'real' AVRs first...

Markus

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm actually having a major drama with these pins, I have wired the _A pins to a host processor's SPI and configured the C1 (almost the same) as an SPI slave with interrupts on and expect to see the SPI ISR executed when 8 bits gets sent from the host. I set SPIPS with the old MCUR |= SPIPS but I get the feeling that it hasn't done anything with it.

 

I thought maybe it matters whether you set up SPI first and then select where it's at but that made no difference.

 

I have a CRO on MISO (not MISO_A) with SPI_A selected via SPIPS (or not?) and send 8 x 8 bits to MOSI_A with a clock on CLK_A and see activity on MISO.

 

What I see is at the time of every block of 8 clocks MISO goes sharply high as if driven, it then stays high for ~10us and then decays to zero exponentially over 430us as is the pin was briefly enabled and as it's only connected to the CRO the 10M I/P impedance is discharging it so about 43pF worth of charge,

 

All of port B where non-SPI_A is has been set as outputs with 0 in the out register.

 

Is there a secret to setting SPIPS?? I've looked far and wide and can't find anything.

 

--

 

OK, I've tried some more things:

 

I configured the SPI_A as the current SPI using (MCUCR |= SPIPS) and configured the SPI as Master with ints off to reduce the amount of SW changes I needed to make.

 

Basically the transmission still went out on port B (regular SPI) pins.

 

I then moved the (MCUCR |= SPIPS) to after the SPI was set up in case that makes a difference and found it didn't fix it. Still uses the regular rather than alternate pins.

 

I sifted through the data sheet to see if this feature was only available on the M1 and couldn't find a reference.

 

I'm stumped.

 

-------

 

Tried some other things, namely seeing whether setting the IVCE bit has an impact and no it doesn't.

 

I think the data sheet's wrong or someone has forgotten to include the unlock mechanism.

Last Edited: Wed. Aug 10, 2016 - 03:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SPI is really good for connecting peripherals like ADC's and DAC's or serial shift registers that you can use to drive LED's.

The micro world wouldn't be the same without it.

 

SPI for serial programming is almost uniquely Atmel. Some others might use it but not standard SPI like Atmel.

 

If I was going to complain about Atmel it would be Atmel Studio 6 and 7, almost unusable compared to studio 4.

 

Studio 4 might have lacked a few features but what was there worked and fast while 6 was as slow as a snail and 7 won't even clear breakpoints half the time, I have to power cycle the emulator. It also clashes with CBuilder, I can't run simultaneous debug sessions.

 

I only ever found 2 issues with 4, first it would lock up if I unplugged the JTAG connector while the programmer was up and running (between chips) and on my laptop the synaptic touch pad driver would hang. Both I could work around.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I set SPIPS with the old MCUR |= SPIPS

When has >>that<< ever worked?

 

 MCUR |= (1<<SPIPS);

SPIPS is a bit >>number<<, not a bit >>mask<<.  Its value is 7.

 

By doing 'the old MCUR |= SPIPS', you were effectively doing this:

 MCUR |= 0x07;

That will set IVSEL and IVCE in the same clock cycle, and will therefore have no effect.  Changing IVSEL requires following a timed sequence involving IVCE.

 

Regardless, it will not set SPIPS.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:-) I have a hammer next to me, can you put me out of my misery? I've been working on MSP430 CBuilder and AVR and long hours to boot.

Only AVR uses (1<<BIT) notation.

You know how it is when you look at the code for so long you don't see anything?

 

Thanks for rubbing my nose in it.

 

- Max

 

Well I never.

 

After correcting your mentioned stupid blunder of mine, my code now reads MCUCR |= (1<<SPIPS);

 

and after that sure enough the SPI CLK_A and MOSI_A pins no longer reflect the data and clock I was seeing but now I can't find those signals on any pin??

 

I tried setting SPIPS before and after the initialisation of SPI as well as moving it to the beginning of the program to no avail.

 

I even tried MCUCR |= (1<<IVCE) just in case.

 

Most confusing.

 

I take it all back, The one thing I need to learn from this exercise is that I can't afford to work through to 5:00am for 2 weeks straight, It makes me surprisingly (for me) susceptible to missing the bleedingly obvious.

 

I love your quotes, please add this one "get some sleep if it doesn't make sense, and if that doesn't make sense take a holiday"

Last Edited: Thu. Aug 11, 2016 - 04:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post some code.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's the code as it is now, and it runs a treat:

 

//**********************************************************************************
//                        Initialise SPI to PUC state
//**********************************************************************************

void InitSPI(void)
{
    // Pin Change Interrupt(s) initialization
    // PCINT0: Off
    // PCINT1: Off
    // PCINT2: Off
    // PCINT3: Off
    // PCINT4: Off
    // PDINT5: Off
    // PCINT6: Off
    // PCINT7: Off
    // PCINT8: Off
    // PCINT9: On                    // /CS pin from Master
    // PCINT10: Off
    // PCINT11: Off
    // PCINT12: Off
    // PDINT13: Off
    // PCINT14: Off
    // PCINT15: Off
    // PCINT16: Off
    // PCINT17: Off
    // PCINT18: Off
    // PCINT19: Off
    // PCINT20: Off
    // PDINT21: Off
    // PCINT22: Off
    // PCINT23: Off
    // PCINT24: Off
    // PCINT25: Off
    // PCINT26: Off

    PCICR=(0<<PCIE3) | (0<<PCIE2) | (1<<PCIE1) | (0<<PCIE0);
    PCMSK0=(0<<PCINT7) | (0<<PCINT6) | (0<<PCINT5) | (0<<PCINT4) | (0<<PCINT3) | (0<<PCINT2) | (0<<PCINT1) | (0<<PCINT0);
    PCMSK1=(0<<PCINT15) | (0<<PCINT14) | (0<<PCINT13) | (0<<PCINT12) | (0<<PCINT11) | (0<<PCINT10) | (1<<PCINT9) | (0<<PCINT8);
    PCMSK2=(0<<PCINT23) | (0<<PCINT22) | (0<<PCINT21) | (0<<PCINT20) | (0<<PCINT19) | (0<<PCINT18) | (0<<PCINT17) | (0<<PCINT16);
    PCMSK3=(0<<PCINT26) | (0<<PCINT25) | (0<<PCINT24);

    // SPI initialization
    // SPI Type: Slave
    // SPI Clock Rate: 1*1,000 kHz
    // SPI Clock Phase: Cycle Start
    // SPI Clock Polarity: Low
    // SPI Data Order: MSB First

    _Select_SPI_A();                // select the alternate SPI Port

    SPCR = ((1<<SPIE) | (1<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA));

    Clr_SPI_Int_Pending();
}

//**********************************************************************************
//                    Clr Pending SPI Int Flag
//**********************************************************************************

void Clr_SPI_Int_Pending(void)
{
// Clear the SPI interrupt flag

uchar Data;

#pragma optsize-
    Data = SPSR;
    Data = SPDR;
#pragma optsize+
//#asm                compiler's assembler doesn't have EQU for spsr/spdr
//    in   r30,spsr
//    in   r30,spdr
//#endasm
}

//**********************************************************************************
//                    SPI Int Routine
//**********************************************************************************

interrupt [SPI_STC] void spi_isr(void)
{
uchar Data;

static uchar Command;
static uchar Idx;
static uchar Address;

    Data = SPDR;                                                                // get byte early
    SPI_Cnt--;                                                                    // one byte less

    _Toggle_Pin();

    switch ( SPI_Data_Idx )
        {
            case 0:

                Command = Data;                                                    // temporarily store command until we know where it's going
                Idx = 0;
                SPDR = SPI_Data_Out[SPI_Data_Idx++];
                break;

            case 1:

                if ( Command != READ_ONLY )                                        // if not a RO command
                    {
                        Address = Data;                                            // now we know the address
                        Tx_DeviceData[Address][Idx++] = Command;                // so save the command
                    }
                SPDR = SPI_Data_Out[SPI_Data_Idx++];                            // either way send next data byte
                break;

            default :

                if ( Command != READ_ONLY )                                        // if not RO command
                    Tx_DeviceData[Address][Idx++] = Data;                        // store command frame

                if ( SPI_Cnt )
                    SPDR = SPI_Data_Out[SPI_Data_Idx++];                        // if more data to go then send
                else
                    if ( Command != READ_ONLY )                                    // if not RO command
                        Queue_CAN_TxD(Address);                                    // queue data to designated target

                break;
        }
}

//***************************************************************************************
//            Pin change 16 interrupt service routine to process SPI /CS                    *
//***************************************************************************************

interrupt [PC_INT1] void pin_change_isr1(void)
{
uchar Address;

    if ( CAN_SELECTED )
        {
            _Set_Pin();
            SPI_Cnt = 8;                                                        // 8 bytes will be transferred
            SPI_Data_Idx = 0;                                                    // CAN data to host index
            SPI_Data_State = 0;                                                    // SPI Rx/Tx State index

            if ( CAN_RxD_Data_Cnt )                                                // if there are any CAN packets waiting
                {
                    Address = Fetch_CAN_RxD();                                    // get next queued data

                    SPI_Data_Out[0] = Rx_DeviceData[Address][0];                // command byte from remote device
                    SPI_Data_Out[1] = Address;                                    // address of remote device
                    SPI_Data_Out[2] = Rx_DeviceData[Address][1];                // 1st data byte from remote device
                    SPI_Data_Out[3] = Rx_DeviceData[Address][2];                // 2nd data byte from remote device
                    SPI_Data_Out[4] = Rx_DeviceData[Address][3];                // 3rd data byte from remote device
                    SPI_Data_Out[5] = Rx_DeviceData[Address][4];                // 4th data byte from remote device
                    SPI_Data_Out[6] = Rx_DeviceData[Address][5];                // 5th data byte from remote device
                    SPI_Data_Out[7] = Rx_DeviceData[Address][6];                // 6th data byte from remote device
                }
            else
                {
                    SPI_Data_Out[0] = NULL_RESPONSE;
                    SPI_Data_Out[1] = 0;
                    SPI_Data_Out[2] = 0;
                    SPI_Data_Out[3] = 0;
                    SPI_Data_Out[4] = 0;
                    SPI_Data_Out[5] = 0;
                    SPI_Data_Out[6] = 0;
                    SPI_Data_Out[7] = 0;
                }
            SPDR = SPI_Data_Out[SPI_Data_Idx];                                    // first byte in SPDR ready to go
        }
    else
        {
            Release_ATT();
            _Clr_Pin();
        }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, your last edit wasn't visible to me when I asked for your code.

 

Glad you got it working.  Get some sleep ;-)
 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]