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.

Is there Z-stack support for external NV memory for OTA on MSP430?

Other Parts Discussed in Thread: Z-STACK, CC2530, MSP430F5529

Hi,

I'm building and app on Z-stack which requires OTA upgrades, thus I've been reading through docs and code on the HW needs. After some reading I thought my best bet would be implementing an external NV memory as my device is an MSP430 with 256KB of flash and my code is already at 112KB, which near the half memory limit for OTA.

My surprise has come when I've found this text in the hal_ota.h of the Z-stack 2.5.1, despite a hal_xnv.c/.h exists:

#if HAL_OTA_XNV_IS_SPI
#error Only Internal XNV is supported.
#else
....

And:

#if HAL_OTA_XNV_IS_INT
#define VDD_MIN_OTA VDD_MIN_NV
#else
#error OTA with external NV on MSP5438 not supported.
#endif

So my question is: Is the external NV memory for OTA upgrades on MSP430 supported in Z-stack?

If it is, which would be the best implementing path?

If it is not: Is there any technical reason for it? and which is my best alternative?

And as a final aside question, looking at the .map file, which sizes compute for the limit for the OTA upgrade? CODE + CONST? or CODE+CONST+DATA?

Thanks a lot for your support.

Best regards,

Asier.

  • Hi again,

    sounds weird but I can find no info on this subject in the Internet nor I get any answer here :-(

    I'm sure I'm not the first one on thinking about this, so:

    Anyone willing to help?

    Thanks a lot!

    Asier.

  • Hi there,

    I've been pursuing some support on this subject from TI, through resellers, through their live chat, and through email.

    In their latest answer the suggest me to reply to myself asking for an update on the status of this "enquiry"... I didn't know I could ask for such a thing here, but here it goes...

    And in the worst case, I hope this will "bump" the post, so maybe someone sees it and can help me. Anyone?

    Does anyone any info or pointer about this?

    TI?

    Thanks a lot,

    Asier

  • Hi,

    It seems that there is less supportive on MSP430 ZStack from TI. I would like to suggest you to apply ZStack on CC2530 directly. We have no problem using different external flash to do OTA on CC2530.

  • Hi,

    Well, thanks for your answer. I suspected there was more support for ZStack on CC2530.

    Unfortunately our platform of choice is MSP430 and we cannot change that, at least not now.

    Best regards,

    Asier.

  • Your  suspiciousness might be right. There might be not more support for CC2530. However, we have the experience to use different external flash to do OTA on CC2530 with ZStack by ourselves and that is why I suggest so. Anyway, good luck to you.

  • Hi,
    I just found my own question in the forum and I've thought I might as well my own answer for other to know.
    At the end, once I found my way around the current XNV management and the OTA Update code, I was able to successfully implement my own library for my external hardware, which is an SPI FLASH memory IC (just for others reference: it's a Microchip 2Mbit - SST25VF020B). It's working flawlessly for the purpose, so far.

    Hope this helps.
    Regards,
    Asier.
  • Hi Asier,

    I'm working on a similar project with a MSP430F5529 with 128KB of flash. I have migrated the z-stack 2.5.1 to work with this MCU, which works fine.

    I'm trying to implement the OTA feature, first with the provided SampleLight/SampleSwitchOta example. I get a linker error ( ), did you get one at the beginning? What MSP430 MCU do you use? I also will have to implement a library to write into external flash memory, could you share your work with me or give me some tips to help me achieve it?


    Thank you in advance.

  • I managed to resolved the linker error, see the post I mentioned in the previous message. I implemented a driver for an external memory chip M25PE20 from Micron. The driver works fine, I write and read back the external memory. I integrated the driver into the SampleSwitchOta example, which properly works. I have tried an OTA upgrade, but it did not complete successfully, despite the external memory driver seems to properly work. I will open another post about this problem.
  • What is the SPI Baud rate you have used ?

    As i am able to write a byte in some random memory location 

    but I am not able to Write continuous stream of bytes sequentially to incremented address ( i tried with AAI programing mode )

  • what is the baud rate you have used for the spi communication?

    I am using the same IC and I am able to read and write ONE byte at any random locations
    I am facing problem with multiple byte Writing

    Here is my function, it is using AAI Mode and Hardware end of detection

    void HAlSPiWrite(uint32 addr, uint8* pBuf, uint16 len)
    {
    //Hardware End of Detection AAI mode
    XNV_SPI_BEGIN();
    xnvSPIWrite(0x70); //EBSY Cmd
    XNV_SPI_END();

    asm("NOP"); asm("NOP");

    XNV_SPI_BEGIN();
    xnvSPIWrite(0x06); //WREN cmd
    XNV_SPI_END();

    asm("NOP"); asm("NOP");

    // Load AAI Command, Address, 2 bytes data -->P16 datasheet
    XNV_SPI_BEGIN();
    xnvSPIWrite(0xAD);
    xnvSPIWrite(addr >> 16);
    xnvSPIWrite(addr >> 8);
    xnvSPIWrite(addr);

    // First Two Byte as per Datasheet Page 16
    do
    {
    xnvSPIWrite(*pBuf++);
    xnvSPIWrite(*pBuf++);

    asm("NOP"); asm("NOP"); asm("NOP");

    #ifdef SOFT_POLLING
    while ( ( ReadStatusReg(SREG_0) & BV(0) ) == 1) //status 0x42 in AAI mode
    #else
    P0SEL &=~BV(2); //MISO as GPIO configured
    XNV_SPI_END();
    asm("NOP");
    XNV_SPI_BEGIN();
    do
    {
    asm("NOP");
    miso_pin = P0_2 ; //reading SO pin Status ( hardware EOD )
    asm("NOP");
    }while(miso_pin != 1);
    XNV_SPI_END();
    asm("NOP");
    XNV_SPI_BEGIN();

    #endif

    P0SEL |= BV(2);
    asm("NOP");asm("NOP");asm("NOP");

    XNV_SPI_BEGIN(); // again transfer ADH followed by data bytes
    xnvSPIWrite(0xAD);
    len -= 2 ;

    if( (len & 1) == 1 ) // if the length is Odd number Avoid unsigned no roll over process
    {
    if( len==65535 )
    {
    break;
    }
    }
    }while (len);

    //WRDI Mode to exit AAI programing mode
    asm("NOP"); asm("NOP"); asm("NOP");
    XNV_SPI_BEGIN();
    xnvSPIWrite(0x04); //WRDI instruction 04H
    XNV_SPI_END();

    #ifndef SOFT_POLLING
    asm("NOP"); asm("NOP"); asm("NOP");
    XNV_SPI_BEGIN();
    xnvSPIWrite(0x80); //DBSY instruction
    XNV_SPI_END();
    asm("NOP"); asm("NOP"); asm("NOP");
    #endif

    ReadStatusReg(SREG_0);
    asm("NOP"); asm("NOP"); asm("NOP");
    }

    What would be WRONN/Missing in this function
  • Hi embRTS,

    I believe your question was for Asier.

    I used the embedded memory chip Micron M25PE20. The SPI clock rate was 12MHz.

    I don't know what is your problem. Did you analyze the SPI transactions with a logic analyzer or a digital scope to ensure they were correct when attempting multiple reading or writing?

    This is the code I used to communicate with SPI. I hope this may help.

    #define XNV_SPI_INIT()  \
    {                       \
      hal_spi_uca1_init();  \
      XNV_RELEASE_CS();     \
      XNV_CONFIG_CS_PIN();  \
      XNV_APPLY_RESET();     \
      XNV_CONFIG_RESET_PIN();\
      asm("NOP"); asm("NOP");\
      XNV_RELEASE_RESET();  \
    }                       \

    #define XNV_RESET_BV            BV(6)
    #define XNV_RESET_PORT          P4OUT
    #define XNV_RESET_DDR           P4DIR
    #define XNV_RESET_SEL           P4SEL
    #define XNV_CONFIG_RESET_PIN()  XNV_RESET_SEL &= ~XNV_RESET_BV; XNV_RESET_DDR |= XNV_RESET_BV
    #define XNV_RELEASE_RESET()     XNV_RESET_PORT |= XNV_RESET_BV
    #define XNV_APPLY_RESET()       XNV_RESET_PORT &= ~XNV_RESET_BV

    #define XNV_CS_BV               BV(7)
    #define XNV_CS_PORT             P4OUT
    #define XNV_CS_DDR              P4DIR
    #define XNV_CONFIG_CS_PIN()     XNV_CS_DDR |= XNV_CS_BV
    #define XNV_RELEASE_CS()        XNV_CS_PORT |= XNV_CS_BV
    #define XNV_SELECT_CS()         XNV_CS_PORT &= ~XNV_CS_BV

    #define XNV_SPI_CONFIG()        UCA1CTL1 |= UCSWRST; UCA1CTL0 |= UCCKPH; UCA1CTL1 &= ~UCSWRST
    #define XNV_SPI_BEGIN()         HAL_DISABLE_INTERRUPTS(); XNV_SELECT_CS()
    #define XNV_SPI_TX(w)           while (!(UCA1IFG & UCTXIFG)); UCA1TXBUF = w
    #define XNV_SPI_RX()            UCA1RXBUF
    #define XNV_SPI_WAIT_RXRDY()    while (!(UCA1IFG & UCRXIFG)); UCA1IFG &= ~UCRXIFG
    #define XNV_SPI_END()           XNV_RELEASE_CS(); HAL_ENABLE_INTERRUPTS()

    void hal_spi_uca1_init(void)
    {
      /* UCLK, MOSI setup, SOMI cleared */
      P4SEL |= BIT0 + BIT4 + BIT5;
      P4DIR |= BIT0 + BIT4;
      P4DIR &= ~BIT5;
      P4DS  |= BIT0;

      /* SMCLK */
      UCA1CTL1 = UCSSEL_2 | UCSWRST;
      UCA1BR0 = 1;  //Normal: SMCLK = 12MHz => SPICLK = SMCLK
                    //Boot  : SMCLK =  1MHz => SPICLK = SMCLK
      UCA1BR1 = 0;

      /* 3-pin, 8-bit SPI master */
      UCA1CTL0 = UCCKPH /*| UCCKPL*/ | UCMSB | UCMST | UCSYNC;

      /* Initialize USCI */
      UCA1CTL1 &= ~UCSWRST;
      UCA1IFG &= ~UCRXIFG;
    }

    static void xnvSPIWrite(uint8 ch)
    {
      XNV_SPI_TX(ch);
      XNV_SPI_WAIT_RXRDY();
    }

    void HalXNVRead(uint32 addr, uint8 *pBuf, uint16 len)
    {
    //  XNV_SPI_CONFIG();
      XNV_SPI_BEGIN();
      do {
        xnvSPIWrite(XNV_STAT_CMD);
      } while (XNV_SPI_RX() & XNV_STAT_WIP);
      XNV_SPI_END();
      asm("NOP"); asm("NOP");

      XNV_SPI_BEGIN();
      xnvSPIWrite(XNV_READ_CMD);
      xnvSPIWrite(addr >> 16);
      xnvSPIWrite(addr >> 8);
      xnvSPIWrite(addr);
      xnvSPIWrite(0);

      while (len--)
      {
        xnvSPIWrite(0);
        *pBuf++ = XNV_SPI_RX();
      }
      XNV_SPI_END();
    }

    void HalXNVWrite(uint32 addr, uint8 *pBuf, uint16 len)
    {
      uint8 cnt;

    //  XNV_SPI_CONFIG();
      while (len)
      {
        XNV_SPI_BEGIN();
        do {
          xnvSPIWrite(XNV_STAT_CMD);
        } while (XNV_SPI_RX() & XNV_STAT_WIP);
        XNV_SPI_END();
        asm("NOP"); asm("NOP");

        XNV_SPI_BEGIN();
        xnvSPIWrite(XNV_WREN_CMD);
        XNV_SPI_END();
        asm("NOP"); asm("NOP");

        XNV_SPI_BEGIN();
        xnvSPIWrite(XNV_WRPG_CMD);
        xnvSPIWrite(addr >> 16);
        xnvSPIWrite(addr >> 8);
        xnvSPIWrite(addr);

        // Can only write within any one page boundary, so prepare for next page write if bytes remain.
        cnt = 0 - (uint8)addr;
        if (cnt)
        {
          addr += cnt;
        }
        else
        {
          addr += 256;
        }

        do
        {
          xnvSPIWrite(*pBuf++);
          cnt--;
          len--;
        } while (len && cnt);
        XNV_SPI_END();
      }
    }