This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Help with Port Mapping

Other Parts Discussed in Thread: MSP430F5418, MSP430F5528

Hi,

I'm trying to change the port mapping on my MSP430F552x MCU so that the SPI ports are outputted as follows:

P4.1: PM_UCB1SIMO (Already set)

P4.7: PM_UCB1SOMI (Remap)

P4.4: PM_UCB1CLK (Remap)

After reading through several tutorials and documentation online, I wrote up the following code in my project:

void systemInit( void )
{

int state;

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
Port_Mapping();

gdevstate.adxl_interrupt_state=0;

setupPorts(); // set up IO ports
setupClocks(); // set up system clock and RTC
timerInit(); // init timer interface
setupSPI();
    ...

void Port_Mapping(void)
{
__disable_interrupt(); // Disable Interrupts before altering Port Mapping registers
PMAPPWD = 0x02D52; // Enable Write-access to modify port mapping registers

#ifdef PORT_MAP_RECFG
PMAPCTL = PMAPRECFG; // Allow reconfiguration during runtime
#endif

P4MAP0 = PM_NONE;
P4MAP1 = PM_UCB1SIMO;
P4MAP2 = PM_NONE;
P4MAP3 = PM_NONE;
P4MAP4 = PM_UCB1CLK;
P4MAP5 = PM_NONE;
P4MAP6 = PM_NONE;
P4MAP7 = PM_UCB1SOMI;

PMAPPWD = 0; // Disable Write-Access to modify port mapping registers
#ifdef PORT_MAP_EINT
__enable_interrupt(); // Re-enable all interrupts
#endif
}

I think the remapping of all 8 ports might be redundant, but I wanted to be sure.  When I test the device I'm trying to use (an ADXL345), I don't get any interrupt data back.  It worked fine before when I used ports that were not remapped.  I had to switch to remapped ports because the final PCB this module is attaching to does not include P4.2 or P4.3.
Does anyone have any suggestions why this may not be working?  Also, if anybody had suggestions for how to visually debug that the port mapping is working (outputting to LEDs, etc), that would be great.

Thanks!
Matt
  • One additional piece of info, this is in the setupPorts() procedure afterwords:

        P4DIR =  BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; //
    P4SEL = 0xFF; //
    P4OUT = 0x00; //
    
    
    Thanks!
    Matt
  • Are you sure you have properly defined PORT_MAP_EINT ? If you have a typo here, it won't throw an error and silently skip the code.
    So interrupts remain disabled and you won't get any interrupts.

    Other than that, I don't see a problem here.

    The only other thing I can imagine is that you removing the UCB1STE mapping might cause a problem. If you use 4-wire SPI mode, it might be that the unmapped STE signal causes the USCI to go into slave mode. Be sure to only use 4-wire mode (which does NOT count the CS line, which is the 5th line then) when you're SPI slave or working in multi-master environment.

  • I notced the PORT_MAP_EINT too and a double-checked that I had it defined.  Also, I am using a 3 wire SPI interface for the ADXL345, so should I still set UCB1STE?  My other quesion is, what sort of bus contention issues are there with using both B0 and B1 for SPI?  Should I be using A1 instead?

  • I'm sorry, I took closer look at the spec and it is 4 wire, so I will trying mapping the STE signal back.  What should the STE signal be set to?

  • A0, B0, A1 and B1 SPI functionalities are independent of each other except one thing: if Ax (or Bx) uses 4-wire SPI, then Bx (Ax) cannot use SPI at all because there are only 6 wires and SPI requires 3 or 4.

    Matt Staniszewski said:
    I took closer look at the spec and it is 4 wire

    Don't get confused here. '4 wire SPI' is actually '4+n wire' where n is the number of slaves. Each slave requires a CS line, but this is plain I/O and doesn't count.

    the 4th wire 'STE' is an input only. If active (from outside master!) it disables the signal pins of the USCI, making it deaf and muted. If teh MSP is master on this specific SPI bus (and the only mastrer) then 3-wire mode must be selected and STE is useless. (again, a 4th wire, the chip select to the slave, is still needed. But it is a software-controlled I/O pin and not handled by the USCI at all, as there can be any number of slaves and CS pins on your bus)

    I was just talking about using 4-wire SPI mode and having th eSTE pin unmapped to a port pin. THi scould have explained your problems. Using 3-wire mode makes STE a don't care, whether mapped or not.
    In your previous (working) code, an unconnected STE pin could have been coincidentally not causing any trouble when your code was using 4-wire mode (since you didn't post your USCI init code, I couldn't know)

    But t is still possible that the problem is somewhere completely else. I never mapped any ports myself and since you say that your code worked with the original pins...

    (btw: does it still work with the new mapping but the hardware connected to the original pins? If so, then no mapping took place)

  • Ok, thanks for the clarification.

    I developed my accelerometer code on a board with a MSP430F5418, which doesn't have any port mapping according to the spec.  Therefore, there's no way for me to go back to the old board and test port mapping.  

    The new board, which uses an MSP430F5528, is a much smaller form factor, and therefore doesn't have all the P4 pins available for me to use, which is why I am using port mapping.  I cannot access the original UCB1 pins on the new board to see if port mapping is/isn't working.

    As for master and slave devices, there's an FRAM module connected to B0 of the MSP430F5528, which uses a 3-wire SPI interface as you described:

    "The SPI interface uses a total of four pins: clock, data-in, data-out, and chip select."

    It seems like B1 should be okay.  I will try defining STE just in case and see what happens.

    Thanks!

    Matt

  • Also, here's the FRAM (B0) and ADXL (B1) init code, which contains the USCI init code:

    #define FRAM_SPI_PxSEL           P3SEL   // Pins select
    #define FRAM_SPI_PxDIR P3DIR // Pins direction
    #define FRAM_SPI_PxIN P3IN // Pins input
    #define FRAM_SPI_SIMO BIT0 // SPI out pin
    #define FRAM_SPI_SOMI BIT1 // SPI in pin
    #define FRAM_SPI_UCLK BIT2 // SPI click pin

    #define FRAM_SPI_IFG UCB0IFG
    #define FRAM_SPI_RXIFG0 UCRXIFG
    #define FRAM_SPI_TXIFG0 UCTXIFG
    #define FRAM_SPI_TXBUF UCB0TXBUF
    #define FRAM_SPI_RXBUF UCB0RXBUF
    #define FRAM_SPI_CTL1 UCB0CTL1
    #define FRAM_SPI_CTL0 UCB0CTL0
    #define FRAM_SPI_BR0 UCB0BR0
    #define FRAM_SPI_BR1 UCB0BR1
    ...
    void NV_FRAM_SPISetup(void)
    {
    FRAM_CS_PxDIR |= FRAM_CS_PxIN; // /CS disable
    FRAM_CS_PxOUT |= FRAM_CS_PxIN;

    FRAM_HOLD_PxDIR |= FRAM_HOLD_PxIN; // /HOLD disable
    FRAM_HOLD_PxOUT |= FRAM_HOLD_PxIN;

    FRAM_SPI_CTL1 |= UCSWRST + UCSSEL_2; // SWRST, SMCLK
    FRAM_SPI_CTL0 |= UCCKPL+UCMSB+UCMST+UCSYNC; // 3-pin, 8-bit SPI master
    FRAM_SPI_BR0 |= 0x02; // UCLK/2
    FRAM_SPI_BR1 = 0;

    // FRAM_MCTL = 0; // No modulation

    FRAM_SPI_PxSEL |= FRAM_SPI_SIMO + FRAM_SPI_SOMI + FRAM_SPI_UCLK;
    // SPI option select
    FRAM_SPI_PxDIR |= FRAM_SPI_SIMO + FRAM_SPI_UCLK;
    FRAM_SPI_PxDIR &= ~(FRAM_SPI_SOMI);

    // SPI TXD out direction
    FRAM_SPI_CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

    //NV_FRAM_EnterSleepMode(); // put FRAM into sleep state to conserve power
    }
    
    
    #define ADXL345_SPI_PxSEL         P4SEL // UCB1
    #define ADXL345_SPI_PxDIR P4DIR
    #define ADXL345_SPI_PxIN P4IN
    #define ADXL345_SPI_SIMO BIT1
    #define ADXL345_SPI_SOMI BIT7

    #define ADXL345_SPI_CLK_PxDIR P4DIR
    #define ADXL345_SPI_CLK_PxSEL P4SEL
    #define ADXL345_SPI_UCLK BIT4

    #define ADXL345_CSn_PxOUT P6OUT
    #define ADXL345_CSn_PxDIR P6DIR
    #define ADXL345_CSn_PIN BIT2

    #define ADXL345_INT1_PxOUT P1OUT
    #define ADXL345_INT1_PxIN P1IN
    #define ADXL345_INT1_PxDIR P1DIR
    #define ADXL345_INT1_PIN BIT2
    #define ADXL345_INT1_PxIE P1IE
    #define ADXL345_INT1_PxIES P1IES
    #define ADXL345_INT1_PxIFG P1IFG

    #define ADXL345_INT2_PxOUT P2OUT
    #define ADXL345_INT2_PxDIR P2DIR
    #define ADXL345_INT2_PIN BIT2
    #define ADXL345_INT2_PxIE P1IE
    #define ADXL345_INT2_PxIES P1IES
    #define ADXL345_INT2_PxIFG P1IFG

    #define ADXL345_IFG UCB1IFG
    #define ADXL345_RXIFG0 UCRXIFG
    #define ADXL345_TXIFG0 UCTXIFG
    #define ADXL345_TXBUF UCB1TXBUF
    #define ADXL345_RXBUF UCB1RXBUF
    #define ADXL345_CTL1 UCB1CTL1
    #define ADXL345_CTL0 UCB1CTL0
    #define ADXL345_BR0 UCB1BR0
    #define ADXL345_BR1 UCB1BR1
    #define ADXL345_MCTL UCB1MCTL
    #define ADXL345_STAT UCB1STAT
    #define ADXL345_UCBUSY UCBUSY
    ...
    void ADXL345_init(void)
    {

    /*
    //2MHz, allowing us to use the fastest data rates.
    spi_.frequency(2000000);
    spi_.format(8,3);

    nCS_ = 1;

    wait_us(500);
    */
    ADXL345_INT1_PxDIR &= ~ADXL345_INT1_PIN; // Set up int 1 pin
    ADXL345_INT2_PxDIR &= ~ADXL345_INT2_PIN; // Set up int 2 pin

    ADXL345_CSn_PxOUT |= ADXL345_CSn_PIN;
    ADXL345_CSn_PxDIR |= ADXL345_CSn_PIN; // /CS disable

    ADXL345_CTL1 |= UCSWRST + UCSSEL_2; // SWRST, SMCLK
    ADXL345_CTL0 |= UCCKPL+UCMSB+UCMST+UCSYNC; // 3-pin, 8-bit SPI master
    ADXL345_BR0 |= 0x10; // UCLK/2
    ADXL345_BR1 = 0;

    // ADXL345_MCTL = 0; // No modulation

    ADXL345_SPI_PxSEL |= ADXL345_SPI_SIMO + ADXL345_SPI_SOMI + ADXL345_SPI_UCLK;
    // SPI option select
    ADXL345_SPI_PxDIR |= ADXL345_SPI_SIMO + ADXL345_SPI_UCLK;
    ADXL345_SPI_PxDIR &= ~(ADXL345_SPI_SOMI);
    // SPI TXD out direction
    ADXL345_CTL1 &= ~UCSWRST; // **Initialize USCI state machine**

    setPowerControl(0); // clear power ctl reg, go into standby
    // setPowerMode(1); // put into reduce power mode
    ADXL345_SetToStandbyMode();
    }
  • Just a quick update, I ran the debugger on my code and when I step through, I noticed that when I hit my port mapping code:

    ...
      PMAPPWD = PMAPPW;                        // Enable Write-access to modify port mapping registers

    #ifdef PORT_MAP_RECFG
    PMAPCTL = PMAPRECFG; // Allow reconfiguration during runtime
    #endif

    P4MAP0 = PM_UCB1STE;
    ...
    
    
    I see that PMAPLOCKED goes to 0 after setting PMAPPWD, but in the next cycle 
    (right before I begin assigning the P4MAP values) I see PMAPLOCKED go back to 1.  
    What could cause this, an interrupt?  I thought I disabled them all.
    
    
    
    
    Thanks!
    Matt
  • Matt Staniszewski said:
    I see that PMAPLOCKED goes to 0 after setting PMAPPWD, but in the next cycle (right before I begin assigning the P4MAP values) I see MAPLOCKED go back to 1.


    PMAPLOCKED has a timeout. It gets automatically reset after a certain number of MCLK cycles. So when you hit a breakpoint, the debugger fetch for variables etc. causes the number of MCLK cycles to pass, so the hardware sets PMAPLOCKED again.
    You can only check this in code. Without breakpoints. Any breakpoint (as well as too much code between two write accesses to the PMM registers) will lock the registers again.

    And yes, of course would do any ISR the same, but you have interrupts disabled (because of exactly this timeout window).

    Know your tools! Often the debugger is a bugger if you don't exactly know how it works.

**Attention** This is a public forum