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.

MSP430FR2422: Access to device descriptors from 0x1A00 to 0x1A23 gives 0x3FFF

Part Number: MSP430FR2422
Other Parts Discussed in Thread: MSP430FR5959,

Hi!

I am trying to port the example codes supported with slau320ai.pdf: "User’s Guide MSP430 Programming With the JTAG Interface".

At the moment I've ported only the relevant functions to get a first access to the device over 2-wire SBW (Spy-Bi Wire) interface.

I am calling GetDevice_430Xv2(). Within the function GetDevice_430Xv2, the first call to GetCoreID() works, then IsLockKeyProgrammed() also works, then GetCoreipIdXv2() works, but then the last call ReadMemQuick_430Xv2() to read the DeviceID does not give the correct response. It should return the value 0x8311 (according to datasheet page 56). Instead it returns 0x3FFF which seems like an error because access to vacant memory is also to described to return this value.

So I tried some accesses to various memory locations.
I can read and write RAM starting from 0x2000.
Descriptor type:
00FF0: 7F80
00FF2: 3524
Start address of descriptor structure:
00FF4: 1A00
00FF6: 0000
--> points to address 0x1A00. That looks correct.
But reading from those addresses gives these results:
01A00: 3FFF
01A02: 3FFF
01A04: 3FFF
01A06: 3FFF

Also I noted a difference between the MSP4302422 and the User's Guide. On page 306 it says the reset value of the FRCTL0 Register is 0x9600. But when I read it, it returns 0x9608. Bit 3 is set. But in the User's Guide bit 3 is zero and marked as "reserved".

I am stuck. In the documentation there is nothing about this area being locked. Why is this behavior?

Does anyone know what's going on here?

  • Hello,

    In the call to ReadMemQuick_430Xv2(DeviceIdPointer + 4, 1, (word*)&DeviceId);, did you confirm DeviceIdPointer has the correct address - 0x1A00?

    Is it possible that there is an access issue, as described in 1.11 Device Security of the User's guide (www.ti.com/.../slau445)

    Srinivas

  • How you reading (F)RAM / TLV? By standard read or by quick read? AFAIK, TLV area can be read only by quick. Again, AFAIK, TLV always start at 1A00, and it is not read protected. I guess that PC from your target device points somewhere else, and quick read return 3FFF.

    I don't have any problem with reading TLV from FRAM with my slau320 based SBW master.

    d:\msp430>flash -f test_msp430fr5959.txt -w -v

    File: "test_msp430fr5959.txt"
    @4400 64512 bytes
    Total Size: 64512 bytes

    Found master device at COM10

    Get Device
    # JTID Fuse Device Core Hard Soft LotWafer DieX DieY
    0  99   OK   6181  1106  30   30  C1F22407 2B00 2200

    Write
    Time: 474 ms  Speed: 132,7 KB/s

    Verify
    Time: 510 ms  Speed: 123,3 KB/s

    Release Device

    Total Time: 1063 ms

  • > How you reading (F)RAM / TLV? By standard read or by quick read?

    In the example code in function GetDevice_430Xv2() it's done with ReadMemQuick. But while fiddling around with this issue I also checked with ReadMem. Both return 0x3FFF.

    > Again, AFAIK, TLV always start at 1A00, and it is not read protected.

    Yes , that's what the datasheet says and also the example code implements. I also read out memory area 0xf00:

    00FF0: 80 7F 24 35 00 1A 00 00

    As you can see the flags are correct and the pointer is pointing to address 0x00001A00. But when reading from 0x1A00 and in particular from 0x1A04 (DeviceID) it gives 0x3FFF over the whole area.

    What bothers me in GetDevice_430Xv2() is the call to GetCoreipIdXv2_430Xv2(). It returns the address to the memory location where the device description lives. It should return 0x1A00 but it gives 0x01A0. In GetCoreipIdXv2_430Xv2() it says:
        IR_Shift ( SBWInstruction::IR_DEVICE_ID ) ;
        // The ID pointer is an un-scrambled 20bit value
        *DeviceIdPointer = DR_Shift20 ( 0 ) ;
    I expected the example code to correct this. And in DR_Shift20() the shifting to flip around the bits is done. But the comment says it's an un-scrambled 20bit value. Why doing the flipping then? Is this a bug or is it intended to do so?

    Be it how it is, I overrided it in the function and set the address manual to 0x1A04 but that did not change anything. In either case, 0x3FFF is returned and that's why I posted in this forum.

    > I guess that PC from your target device points somewhere else, and quick read return 3FFF.

    I had the same idea. In another post I asked about the PSA engine. For testing I used VerifyPSA_430Xv2() with an address in FRAM and length=1 word. Interestingly the value returned is identical with a value as if the PSA engine is reading 0x3FFF from the given location. However, reading from and writing data to the FRAM did work.

    That also looks like there is an issue reading data from the correct address. But this time it's the PSA engine. Or maybe it's the CPU moving data around and is not allowed to access. But this seems not likely because my DUT is MSP430FR2422 and this device does not have the complex protection flags that are found on other devices.

  • I checked the address. There is the pointer to 0x1A00 in those memory locations. I also made accesses manually with fixed addresses and the using ReadMem or ReadMemQuick. Still the same problem. Any access to address ranges 0x1A00... return 0x3FFF.

    And I checked for access issues (mabe protection flags.) Since EraseFRAMViaBootCode() works this function mass erases the FRAM and it is no issue. I can program the region 0xFF80..0xFF83 and the SBW interface is locked as described by the user's guide. At start the FUSE is correctly reported to be set. Then I can invoke EraseFRAMViaBootCode() and the mass erase resets everything. It's not a permanantly lock.

    I also suspected the function ReadMemQuick as the culprit and so I compared it with the flow described in 2.3.3.3.1 in the user's guide. But everything is fine.

    Any idea what else I can check?

    Are there other (more basic) example codes to test the CPU or the registers besides the examples in the Replicator430FR or SimpleLink Host code?

  • Hi! In the meantime, I've got it working.

    The first problem is clock timing issues. I based my code on the Replicator430FR source found in slau320ai. There are inconsistent definitions for setting/clearing the signals.
    For example:
    1)    #define ClrTCLK()  ClrTCLK_sbw()
           when this definition is used, there is no delay in the function.
    2)    #define ClrTST()   (JTAGOUT &= ~SBWCLK)
           also in the definition there is no delay.
    3)    #define TMSLDH {JTAGOUT &= ~SBWDATO; nNOPS JTAGOUT &= ~SBWCLK; nNOPS JTAGOUT |= SBWDATO; JTAGOUT |= SBWCLK;}
           as you can see, in this definition there are delays inserted with nNOPS.
    The same applies to the SBWDIO signal. Some definitions have delays and some don't.

    I made a major overhaul of the replicator code and in the end every signal change is done with the following four definitions. A delay is now always applied to avoid signal switching too quickly.

    void DELAYsbw ( void ) { waitFor_ns(300); }   // 5 NOP cycles (@18 MHz) --> 5*(1/18MHz) = 278ns
    inline void ClrSBWTCK ( void ) { my_sbwClock->SetLow(); DELAYsbw(); }
    inline void SetSBWTCK ( void ) { my_sbwClock->SetHigh(); DELAYsbw(); }
    inline void ClrSBWTDIO ( void ) { my_sbwData->SetLow(); DELAYsbw(); }
    inline void SetSBWTDIO ( void ) { my_sbwData->SetHigh(); DELAYsbw(); }

    The second problem is a bug in the Replicator430FR source. The same bug can be found in SBW430FR.c of the "SimpleLink Host for MSP430 SBW" source:

    word GetCoreipIdXv2()
    {
        IR_Shift(IR_COREIP_ID);
        CoreId = DR_Shift16(0);
        if(CoreId == 0)
        {
            return(STATUS_ERROR);
        }
        IR_Shift(IR_DEVICE_ID);
        DeviceIdPointer = DR_Shift20(0);
        // The ID pointer is an un-scrambled 20bit value
        return(STATUS_OK);
    }

    There is a github project that implements a DLL for MSP430. See https://github.com/BuLogics/libMSP430

    Deep down in the code there is HAL_FUNCTION(_hal_GetJtagId) that can be found in https://github.com/BuLogics/libMSP430/blob/master/Bios/src/hal/macros/GetJtagId.c

        // Get Core identification info
        core_ip_pointer     
        SetReg_16Bits(0);
        CoreIpId = lOut;
        // Get device identification pointer
        device_ip_pointer
        SetReg_20Bits(0);     
        DeviceIpPointer = lOut_long;
        // The ID pointer is an un-scrambled 20bit value
        DeviceIpPointer = ((DeviceIpPointer & 0xFFFF) << 4 )  + (DeviceIpPointer >> 16 );

    The important difference is the last line. You can see the comment is the same but the Replicator code does not correct the scrambled pointer. I added this correction to my code and it solved the problem.

    Thanks to TI for delivering bad code. And you haven't tested it. Otherwise you should have noticed the mistake!
    It's great that I was allowed to search for your mistakes for days!!!

**Attention** This is a public forum