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.

MSP430 REGISTERS

Other Parts Discussed in Thread: MSP430F2131

I've been using the MSP430 since 1998, and, despite trying various other micros still keep churning out designs based around this thing, manly because I like the timers especially, but most other peripherals are decent and mostly easy to use. I have always had one wish above everything else (well 2 actually, one being orthogonal src/dst addressing) and that is for more registers. I write pretty much exclusively in assembler for the MSP430 (whatever happended to the assembler samples::) and the registers are amazingly useful when it comes to speeding up your code, but I always run out of them far too quickly, plus there is always that evil bug when you forget that a regsiter has been allocated to a forground task, then you use it in an interrupt handler. There are lots of spare bits in the Status register, so my thought has always been to either select a bank using a bit in the SR or to simply allocate one set of registers to be available for ISR use only (less useful, but possibly easier to do) with a mechanism to allow access to them.  ISR's are particularly important because they need to be as concise and fast as possible. I tend to run lots of ISR's, and you need to know how long your ISRs take to execute worst case so that you can ensure there are no misses, or clashes. Also on comms intensive or even some I/O intensive designs it would make a huge differenc eif you could allocate often use variables to registers. Or even do this in loop control for foreground routines

  • Hello Onestone,

    Thank you for your comments, I will be sure to forward your feedback to the proper Design Team. Can you further explain what you mean by running out of registers too quickly? I would not refer to the upper byte of the SR as spare bits, rather they are reserved for internal use by the MSP430. Typically the interrupt vector table and corresponding IFG bits are sufficient for distinguishing between and addressing ISRs, but I do understand your concern about executing an ISR as quickly as possible. Interrupt priority settings and nesting are often useful for ensuring that there are no misses or clashes between ISRs however there are some outlying cases that are difficult to account for. It takes 6 clock cycles to enter an ISR and 5 clock cycles to exit it, additional time depends on what your application is doing inside of the ISR. Utilizing the DMA peripheral can sometimes be a solution to avoiding time-costly ISRs altogether. Instead of allocating variables to registers, why not skip variable use completely and directly control the register?

    Also, do you have any specific questions that I can help address?

    Regards,
    Ryan
  • Hi Ryan, well I tend to write only in assembler, for various reasons, mainly though because, having used most programming languages over the last 40+ years i find assembler the neatest, and simplest to get the sort of performance I want. I also often have fairly intensive programs, for example running 3 spi based 3 axis sensors at 5000 samples a second while also running a UART at 460kB and an SD card that must record the sensor data in real time. So the DMA is of limited use. I did allocate it to the SD card, but it isn't a true DMA in that it does steal CPU cycles, so is of limited use in any process intensive operation. In addition I often use small parts to do big jobs, for example image encoding and recognition on  an MSP430F2131, and they don't have DMA. Most applications are ISR intensive, but to keep the overhead down I like to dedicate registers to certain functions, especially the centre code in nested loops. I often find that I could do with more registers to get the performance I want, whereas I can't afford the board space to use an MSP with more memory or peripherals, or power needs to move to a larger faster micro family.

    For example the following part of a header file defines register use on one design that used multipl SPi ports, and I wopuld have liked to dedicate registers to each port, but ran out of registers very quickly. A second set would have been extremely useful.  I understand that the operand structure makes it impossible (virtually) to add 16 more registers directly which is why I suggested a second, or even a third set that are paged in, or inferred perhaps. I am all about clock cycles, I haven't needed the reference books to count clock cycles for years, I can simply count them as I go. here's the code that shows the problem, R15 wasn't used at the time the header was written because having only one of the 3 values I used per channel had little benefit, however it was co-opted into a second dedicated ISR register later:-

    ****************************************************************************/
    #define          ACCPTR        R4    //REPLACED BY ACC1CNT & ACC2CNT
    #define          ACCCNT        R5    
    #define        ACCDAT        R6                    
    #define        EVTPTR        R7                    
    #define          SDLEN        R8                    
    #define        SDDAT        R9                    
    #define          SDCOUNT      R10                    
    #define          SDVECTOR      R14                    


    /*
        R11    IS A GENERIC POINTER USED IN MODULE 'EVENTS'
        R12    IS A GENERIC DATA HOLDER USED IN MODULE 'EVENTS'
        R13    IS RESERVED FOR ISR USE
        R15     IS CURRENTLY NOT USED
    */

  • Hi Ryan,

    Unlike your use cases, I always try to code C/C++ as efficient as assembly. I have been using TI SoC for over 20 years. 20 years ago, TI was very famous with its DSP chips. It was very important to code in assembly at that time to achieve good performance. And then, the C compiler and optimiser provided by TI got better and better. The key concept is to know how C compiler will arrange registers for various conditions. That means, I already know what the disassembly will look like when coding in C.

    As time goes by, the main trend of CPU design is to use 16 registers for micro controllers. MSP430 has R0 to R15. Cortex M has the same number. The reason is simple, it takes time to save and restore registers for ISR. More registers take more time. For a general RTOS, all registers must be saved/restored, not partial.

    Another reason is, it is too difficult to maintain assembly code manually. Even you can do it, others who take over your projects might not.

    Unlike your cases to push MSP430 to the limit, I even tried to use C++ in micro-controllers. I have ported my RTOS to MSP430 and M3 two years ago. And recently, I added C++ capability directly in RTOS so that application can create a C++ "Task" object directly as shown in the following code piece, the virtual function, run(), will be executed automatically when MyTask object is created and resumed to run. All are supported natively by my RTOS. The reason for me to do this is, I think it is more and more important to use higher level programming skill in the future because SoC needs to do more and more tasks. The C++ object encapsulation capability is very useful to make program structure clear and easier to maintain.

    class MyTask: public Task
    {
    private:
    public:
    void run();
    }

    Anyway, honestly, I don't think your "wish" will come true.