portSTACK – 20-bits

Hello, I’m working on a port in which the portSTACK type needs to be 20-bits – has anyone done a port with this being 20-bits wide? If so – can you elaborate on how you made it work? Thanks, John W.

portSTACK – 20-bits

How does this work then at the processor level?  Is the RAM 16bits wide, or 20bits wide? Regards.

portSTACK – 20-bits

Richard, Registers can be used in either 16 or 20-bit mode.  Memory is addressable to 1MB; so addresses can go to 20-bits.  RAM is 16-bits wide.  Wordsize is 16 bits. Issue I’m having is using memory above 64K.  RAM resides in lower 64.  Flash is only located above 64K. Thanks, John

portSTACK – 20-bits

Richard, I guess I should’ve said real issue is pushing 20-bit registers on the stack and how to handle in port.c …. Thanks, John W.

portSTACK – 20-bits

The PIC24 does simlar things.  Pointers are 16bits, but the address space is 24bits – which makes it seem tricky to point to the start address of a task.  Luckily in this case the compiler takes care of it for you through the use of a poitner jump table. So what does the processor do when it stacks 20bit registers into 16bit wide RAM?  (I could always read the datasheet but I’m a bit pushed for time).  Does it just loose 4bits of the third register byte?  The MSP430 has quite a few registers, so this would seem wastefull, but maybe this is not a problem as you get a lot more memory space to play with. Is your problem then that you cannot declare the stack type as 16bits, as they are in fact 20bits, and you cannot declare the stack type as 32bits, as this gives you a whole byte (plus the 4 bits) too much (sorry for basic questions).  Seems a bit tricky. Regards.

portSTACK – 20-bits

Richard, Yes – I can’t declare portSTACK as 20-bits wide. From the datasheet on a push: The stack pointer (SP) is decremented by two (byte and word operands) or by four (address-word operand) before the write operation. From the datasheet for a pop: The stack pointer SP is incremented by two (byte and word operands) and by four (address-word operand). Thanks, John

portSTACK – 20-bits

It sounds like it is using 32bits per 20bit value, in which case this would make the stack type unsigned long.  You would have to setup the initial stack in port.c using 4bytes per 20bit register. Regards.

portSTACK – 20-bits

Richard, Yes – that’s what I’m trying to do now. I’ll let you know how it goes. Thanks, John

portSTACK – 20-bits

Richard, Looks like everything is OK up until the portRESTORE_CONTEXT when xPortStartScheduler is called – as soon as the reti is called – the app goes into the weeds. Everything looks ok – the starting addr of the 1st task is where it’s supposed to be – but it’s 32 bits now vs. 16 (or 20) – maybe that’s where things are going wrong… Regards, John

portSTACK – 20-bits

In your debugger, are you able to break in an interrupt routine, then inspect the stack just before a compiler generated reti instruction, so you can inspect the stack to see how the address is stored?  You can then copy this.  Maybe there is some magic somewhere, as per the PIC24 jump table mentioned previously. Regards.

portSTACK – 20-bits

Richard, One of the issues is in port.c – if everything is made 32-bits – including pxCode and portFLAGS_INT_ENABLED – from the databook on RETI: RETI Return from interrupt Syntax RETI Operation @SP → SR.15:0 Restore saved status register SR with PC.19:16 SP + 2 → SP @SP → PC.15:0 Restore saved program counter PC.15:0 SP + 2 → SP House keeping Description The status register is restored to the value at the beginning of the interrupt service routine. This includes the four MSBs of the program counter PC.19:16. The stack pointer is incremented by two afterwards. The 20-bit PC is restored from PC.19:16 (from same stack location as the status bits) and PC.15:0. The 20-bit program counter is restored to the value at the beginning of the interrupt service routine. The program continues at the address following the last executed instruction when the interrupt was granted. The stack pointer is incremented by two afterwards. Looks like 16-bit values are expected – not 32-bit.  I did a fix up on this and got a little further down the road – but the app still goes in the weeds. Since I had the portFLAGS_INT_ENABLED set to be 0x08 – this was stored as 0x00000008 – and after the RETI was done – the 0x0008 was being grabbed by the SR but the PC was being set to 0x0000;  The task’s address was after that – stored as 0x0000383E; – but the PC didn’t get that far since jumping to weed-land at 0x0000; I’m going to have to stop for today but I’ll be back at it this weekend. Thanks, John

portSTACK – 20-bits

So 4 bits of the program counter are stored in the unused bits of the stack pointer.  Looks like you are going to have to do some shifting of values in pxPortInitialiseStack() to get everything in the right place.  There is a port that does this already I think (?) but I cannot remember which processor it is. Can you provide me with a part number or a link to a document that describes the architecture?  I’ve looked at a couple on the TI site but they seem to have 16bit program counters. Regards.

portSTACK – 20-bits

Richard, Yes, I did some shifting at the beginning of xPortInitializeStack() but more needs to be done. The MPS430 Family is the MSP430FG4XXX – the one’s I’m using specifically are the MSP430FG4618 and MSP430FG4619 The datasheet can be downloaded from: http://focus.ti.com/lit/ds/symlink/msp430fg4618.pdf The UG can be downloaded from: http://focus.ti.com/lit/ug/slau056f/slau056f.pdf Chip errata can be downloaded from: http://focus.ti.com/lit/er/slaz028f/slaz028f.pdf Main Page for the ‘FG4618: http://focus.ti.com/docs/prod/folders/print/msp430fg4618.html Thanks! John

portSTACK – 20-bits

Richard, I’m getting to the first vTaskDelayUntil – and when the RETA is executed – it bombs. It looks like the SP may be off by one word – I just took a closer look in the debugger – and for some reason – this is what it looks like – there’s a popw.m #6,R11 in vPortYield(); – and it looks like where the SP is pointing is SR info – (one word) – then the address of what should be executed – like what you’d expect in a reti – but in this case it’s a RETA – from the datasheet: * RETA Return from subroutine Syntax RETA Operation @SP → PC.15:0 LSBs (15:0) of saved PC to PC.15:0 SP + 2 → SP @SP → PC.19:16 MSBs (19:16) of saved PC to PC.19:16 SP + 2 → SP Emulation MOVA @SP+,PC Description The 20-bit return address information, pushed onto the stack by a CALLA instruction, is restored to the program counter PC. The program continues at the address following the subroutine call. The status register bits SR.11:0 are not affected. This allows the transfer of information with these bits. So – this is different than RETI – the SR isn’t affected – so the PC is picking up what looks like the SR info and then entering weed-land. But – it looks like the SP is pointing to what would be expected by a RETI vs. a RETA. At least this is progress… Thanks, John W.

portSTACK – 20-bits

Actually the above is in taskYield() – immediately following the call to vPortYield()… John

portSTACK – 20-bits

It is interesting to note that the stacking of the address is different between CALLA/RETA and Interrupt/RETI.  In the interrupt case PC.15:0 is pushed first, while in the CALLA case PC.15:0 is pushed last.

portSTACK – 20-bits

Looks like the issue is boiling down to differences in RETI, RETA, and RET. Regards, John

portSTACK – 20-bits

Richard, After doing the ‘shift fix-up’ – could that affect the tskTCB down the road?  I’ve looked that this and don’t think so – but wanted to see what you thought. Thanks, John

portSTACK – 20-bits

1st context switch from IDLE to LEDx task is where this is currently dieing…

portSTACK – 20-bits

I would not have thought so….but Regards.

portSTACK – 20-bits

Richard, Yep – I think …but may be right here. I’ll revisit this when I get time – or when trying to help others like Penn gives me those ‘oh yeah’ moments thus causing me to check things out… Regards, John W.

portSTACK – 20-bits

Richard, I think I may have mentioned this before – I do get 166 ticks on the clock before the <kablam!> happens – so that indicates a lot is working OK. Regards, John

portSTACK – 20-bits

I’m not sure where you are at now, but I have a few thoughts – which may just be re-iterating what has been said so far. Since it is possible for a context switch to occur while the PC is in 20-bit space, the portSAVE_CONTEXT and portRESTORE_CONTEXT macros probably have to handle by default the 20-bit case.  This means that all of the push and pops need to be the .A versions so that the 20-bit registers are pushed onto the stack. Since this requires 32-bits per register, this requires twice as much stack space relative to the 16-bit version.  This means that the CCE compiler needs to use the mspx core as the msp core does not support the extended instruction set. In the portYIELD() function, the stack will have to be manipulated to combine the upper 4 bits of the PC with the SR as well as reversing the word order.  This will be difficult as it seems that the PC19:16 needs to be shifted to the left and have the SR added to it, without affecting the SR in the process (if you figure this out before me, please post the code), followed by a swap of this location and the location on the stack containing PC15:0. It may end up being easier to push the SR onto the stack, and use portRESTORE_CONTEXT with the RETA instruction (however, this would still require some manipulation for the case of the the portTICK_ISR(), since the stack coming in due to an interrupt is not correct for a RETA instruction).  All of this assumes that portYIELD() is called with a CALLA instruction (not a CALL instruction). This also means that you need to make sure the compiler is using the CALLA instruction when calling portYIELD() so that the stack is as expected.  I think the Large Memory Model option in the CCE compiler forces all functions to use CALLA and RETA. Hope this at least spurs some thoughts. I probably also will be working on a port for CCE as I just had to shift from the F449 to the FG4618 due to a need for RAM. Penn

portSTACK – 20-bits

Penn, I might suggest just using the ‘FG4618 in 430 mode for now vs. 430X mode.  You will have access to all peripherals save FLASH above 0xFFFF. I’m busy working on a C8051 IAR port at the moment so I won’t be back on this for a while. I do have a stable 430-mode port running on the ‘FG4618 (IAR). Regards, John

portSTACK – 20-bits

I have a port attempted – figured out the assembly code I need.  However, when I start the schedular, and step through the taskRESTORE_CONTEXT() macro, it resets when a popx.w r15 instruction executes.  The SP seems to be pointing to a valid, even, RAM location.  Any ideas? Penn

portSTACK – 20-bits

You’re not running in ‘true’ 430X mode (I just made that ‘definition’ up – so it’s somewhat tongue-in-cheek) – but the pop instruction should be: popx.a   r15 …. If 430 & 430X modes get mixed – you get bits ‘lurking’ in the upper 4 positions – and end up with a situation that doesn’t work – which sounds like what is happening. You may have to some assembler to get this to work – look at the Rowley MSP430 port for some starting ideas or look at the MSP430 ports on my site. I don’t think you will have 100% control on when the compiler decides to use CALL vs. CALLA – which could lead to the above – which is why you may need to convert some routines to assembler. HTH, John W.

portSTACK – 20-bits

Maybe a way to ‘fix’ this is to issue CLR instructions at the appropriate time – would be useful if TI had supplied a ‘CLEAR MULTIPLE’ command – i.e. – CLRM.A command. This in fact may be a way to fix the problem.  The 20 vs. 16 bit issue is particularly ugly if the PC gets corrupted in 16 vs. 20-bit mode – meaning the upper 4 bits are set when the PC is restored to a ‘near’ address making the PC happily jump into weedland – somewhere > 0x10000 (running in 430 mode). 20-bit push occurring when a 16-bit should’ve occurred – or 20-bit pop occuring where 16-bit should’ve occurred – or vice-versa. Regards, John W.

portSTACK – 20-bits

From what I understand, it is ok to "mix" popx.w and popx.a.  I believe that when popx.w Rn is used, it automatically clears bits 19:16 of Rn while placing the word on the stack into 15:0, and decrements the stack pointer by 2. I am stepping through the code and the stack pointer is in RAM – the upper 4 bits of the SP are clear – right before the "popx.w R15" sends my debugger into the weeds.  Issuing a popx.w R15 command shouldn’t affect either the SP or the PC, so I am confused why stepping into this instruction is causing my debugger to go into the weeds.  I will change it to a popx.a instruction just for a test to see if it improves my situation (knowing I will have to change the corresponding pushx.w instruction to pushx.a as well).  I suspect that there is something else going on that I am missing and the debugger is not showing me good information. Penn

portSTACK – 20-bits

BTW, I think the CCE compiler uses strictly CALLA and RETA when using the mspx core.

portSTACK – 20-bits

Wouldn’t count on it.  If you’re operating in the lower 64 – then CALL’s work fine.  I would think a ‘short’ call would only use CALL’s.  I wouldn’t trust any compiler until I looked at 100% of the assembly in this case.

portSTACK – 20-bits

CCE says that to mix assembler and C, always use CALLA and RETA in the assembler.  This implies that all the functions use this, as otherwise a C function could be called from assembler with a CALLA that returned with a RET. I figured out my bug – I was writing to an undefined are of the SFRs – pointer issue.  The debugger was masking it as it is slow and awkward with the MSP430X. Here are some snippets of my port.  Note that the portSTACK_TYPE should be portSTACK_SHORT as in other MSP430 ports, even though some function pointers are 20-bits.  This works because all stack pointers are in RAM and are 16-bit. #define portSAVE_CONTEXT()                                asm (    " pushm.a    #12,r15");                        asm    (    " movx.w    usCriticalNesting,r15");        asm (    " pushx.w    r15");                            asm (   " movx.w    pxCurrentTCB,r12");                asm (   " movx.w    r1,0(r12)"); #define portRESTORE_CONTEXT()                                asm (    " movx.w    pxCurrentTCB, r12");                asm    (    " movx.w    0(r12),r1");                        asm    (    " popx.w    r15");                                asm    (    " movx.w    r15,usCriticalNesting");            asm    (    " popm.a    #12,r15");                            asm (    " reti"    ); void vPortYield( void ) {     /* We want the stack of the task being saved to look exactly as if the task     was saved during a pre-emptive RTOS tick ISR.  Before calling an ISR the     msp430 places the status register onto the stack.  As this is a function     call and not an ISR we have to do this manually. */     asm ( " pushx.w     r2" );     _DINT();         /* Make stack look like we entered form an ISR instead of a CALLA */     asm ( " bicx.w         #0xF000,0(r1)");     asm ( " swpbx.w        +4(r1)");     asm ( " rlax.w        +4(r1)");     asm ( " rlax.w        +4(r1)");     asm ( " rlax.w        +4(r1)");     asm ( " rlax.w        +4(r1)");     asm ( " addx.w         +4(r1),0(r1)");     asm ( " movx.w         +2(r1),+4(r1)");     asm ( " movx.w         0(r1),+2(r1)" );     asm ( " incdx.a        r1"); … The pushm.x #n,Rx instruction and corresponding popm.x instruction, while placing n registers on the stack with one instruction, place the registers on the stack in the opposite order of pushing and popping one at a time.  Therefore, the pxPortInitialiseStack function needs to account for this and reverse the R4 to R15 initialization values. portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) {     /*         Place a few bytes of known values on the bottom of the stack.         This is just useful for debugging and can be included if required.         *pxTopOfStack = ( portSTACK_TYPE ) 0x1111;         pxTopOfStack–;         *pxTopOfStack = ( portSTACK_TYPE ) 0x2222;         pxTopOfStack–;         *pxTopOfStack = ( portSTACK_TYPE ) 0x3333;         pxTopOfStack–;     */     /* The msp430 automatically pushes the PC then SR onto the stack before     executing an ISR.  We want the stack to look just as if this has happened     so place a pointer to the start of the task on the stack first – followed     by the flags we want the task to use when it starts up. */     *pxTopOfStack = ( portSTACK_TYPE ) pxCode;     pxTopOfStack–;     *pxTopOfStack = ((( portSTACK_TYPE )((((unsigned long)(pxCode)) >>4) & (0x0000F000))) | portFLAGS_INT_ENABLED);     //*pxTopOfStack = portFLAGS_INT_ENABLED;     pxTopOfStack–;     /* Next the general purpose registers. */     /* When the task starts is will expect to find the function parameter in     R15. */     *pxTopOfStack = (portSTACK_TYPE) ((((unsigned long)pvParameters)>>16) & (0x0000000F));     pxTopOfStack–;        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x000e;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0xeeee;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x000d;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0xdddd;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x000c;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0xcccc;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x000b;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0xbbbb;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x000a;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaa;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0009;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x9999;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0008;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x8888;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0007;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x7777;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0006;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x6666;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0005;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x5555;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x0004;     pxTopOfStack–;     *pxTopOfStack = ( portSTACK_TYPE ) 0x4444;     pxTopOfStack–;     /* The code generated by the mspgcc compiler does not maintain separate     stack and frame pointers. The portENTER_CRITICAL macro cannot therefore     use the stack as per other ports.  Instead a variable is used to keep     track of the critical section nesting.  This variable has to be stored     as part of the task context and is initially set to zero. */     *pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_SECTION_NESTING;        /* Return a pointer to the top of the stack we have generated so this can     be stored in the task control block for the task. */     return pxTopOfStack; } Penn

portSTACK – 20-bits

Penn, Looks like you have solved this – great job! As long as a vPortYield will always occur during a CALLA/RETA frame – this should always work.  I wasn’t 100% sure this could be relied upon since I wasn’t sure the compiler wouldn’t ‘mix’ CALL and CALLA frames. I will code up a test and try to force calls with function pointers > 0x10000 to be yielded to make sure this works in all instances. Thanks! John W.

portSTACK – 20-bits

I’ll try to remember to send you my port.c and portmacro.h tomorrow when I get back to work. Penn

portSTACK – 20-bits

Penn, OK – please do that. I just tried this – plus I tried some ideas I had – definitely got the system running with some tasks running – but – I have a RX_IRQ that caused the system to crash only after a few times of it being used – so evidently there’s still some work to do. This is good progress though. Thanks, John W.

portSTACK – 20-bits

How many times is your TICK running before it crashes (ie, is it crashing on the first tick or have you concluded it is definately related to the RX_IRQ)?

portSTACK – 20-bits

Penn, As I mentioned – several tasks are actively running – LED’s blinking, several IRQ’s running, etc. The xTickCount counter has rolled many times before this happens. Please check this if you would on your end with a serial ISR maybe doing something simple like copying received chars and just echoing them back out. The same code I have runs fine in 430 mode – so the error is more than likely related to the port (430X). Are you able to run the demo code in 430X mode – including the Serial ISR demo, with no problem? Thanks, John

portSTACK – 20-bits

I have not tried the demo code as I have my own hardware and software – a completely different application. I have TIMERB interrupts going – they are yielding and resuming tasks.  I also have a simple serial ISR that collects data and places into a buffer – but I haven’t tried it yet as I am waiting on some other hardware. Could you send me or post a copy of your serial ISR so I can take a quick look at it? Also, the stack size needs to increase when using the 430X because the full 20-bits of the registers are saved on the stack (consuming 4-bytes) instead of just the lower 16-bits.  Perhaps your ISR is interrupting a task that is near the end of the stack. Penn

portSTACK – 20-bits

Penn, et. al, I have the IAR (4.10D) port running on the TI MSP430(X) Experimeter Board – using the latest posted v.4.7.1 FreeRTOS ‘core’ code. There are a few differences with my board(s) – I have the ‘4619 on my board(s) vs. the ‘4618 – and I’m using an 8MHz clk (X1) on my board(s). I have the LED demo running – LED’s 1, 2, and 4 – and I have the Com Test Running – 115.2KB – running out of the 9-Pin DB-9 (RS-232) port. If anyone is interested in the port – you can send me an e-mail and/or download it from my web-site.  I will try to post it soon – so be patient if you want to download it from my site.  The port seems to be stable so far – I want to thank Penn for his dialogue and suggestions on this port. Regards, John C. Westmoreland www.WestmorelandEngineering.com john at westmorelandengineering dot com