@@ -645,7 +645,6 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
645645 ( await this . getExprVal ( '(char *)' + thInfo [ 'pcTaskName' ] ?. exp , frameId ) ) || '' ;
646646 const match = tmpThName . match ( / " ( [ ^ * ] * ) " $ / ) ;
647647 const thName = match ? match [ 1 ] : tmpThName ;
648- const stackInfo = await this . getStackInfo ( thInfo , 0xA5 , frameId ) ;
649648 // This is the order we want stuff in
650649 const display : { [ key : string ] : RTOSCommon . DisplayRowItem } = { } ;
651650 const mySetter = ( x : DisplayFields , text : string , value ?: any ) => {
@@ -692,6 +691,7 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
692691 }
693692 }
694693 }
694+ const stackInfo = await this . getStackInfo ( threadRunning , thInfo , 0xA5 , frameId ) ;
695695 mySetter ( DisplayFields . StackStart , RTOSCommon . hexFormat ( stackInfo . stackStart ) ) ;
696696 mySetter (
697697 DisplayFields . StackTop ,
@@ -750,15 +750,16 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
750750 } ) ;
751751 }
752752
753- protected async getStackInfo ( thInfo : RTOSCommon . RTOSStrToValueMap , waterMark : number , frameId : number ) {
753+ protected async getStackInfo ( threadRunning : boolean , thInfo : RTOSCommon . RTOSStrToValueMap , waterMark : number , frameId : number ) {
754754 const pxStack = thInfo [ 'pxStack' ] ?. val ;
755755 const pxTopOfStack = thInfo [ 'pxTopOfStack' ] ?. val ;
756756 const pxEndOfStack = thInfo [ 'pxEndOfStack' ] ?. val ;
757757 const stackInfo : RTOSCommon . RTOSStackInfo = {
758758 stackStart : parseInt ( pxStack ) ,
759759 stackTop : parseInt ( pxTopOfStack )
760760 } ;
761- const mpuStackTop = await this . mpuGetStackTop ( thInfo , frameId ) ;
761+
762+ const mpuStackTop = await this . mpuGetStackTop ( threadRunning , thInfo , frameId ) ;
762763 if ( mpuStackTop === null ) {
763764 stackInfo . stackTop = undefined ;
764765 } else if ( mpuStackTop !== undefined ) {
@@ -817,6 +818,7 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
817818 // * undefined: no MPU context was found (meaning pxTopOfStack can be used for deltas)
818819 // * null: MPU context was found, but could not be interpreted (unsupported architecture, unexpected size, etc.)
819820 private async mpuGetStackTop (
821+ threadRunning : boolean ,
820822 thInfo : RTOSCommon . RTOSStrToValueMap ,
821823 frameId : number
822824 ) : Promise < number | null | undefined > {
@@ -825,8 +827,11 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
825827 }
826828 const xMPUSettings = ( await this . getVarChildrenObj ( thInfo [ 'xMPUSettings' ] . ref , 'xMPUSettings' ) ) || { } ;
827829
828- // non-privileged tasks use a separate system call stack, and back up
829- // their task SP. Use that backup if it's present and non-NULL.
830+ // When a non-privileged task voluntarily relinquishes the CPU,
831+ // uxContext contains a pointer into the system call stack, rather than
832+ // the task stack. While that task is paused, pulTaskStack
833+ // (pulTaskStackPointer on some ports) will contain a backup of the
834+ // task's stack pointer. (continued...)
830835 if ( 'xSystemCallStackInfo' in xMPUSettings ) {
831836 const xSystemCallStackInfo =
832837 ( await this . getVarChildrenObj ( xMPUSettings [ 'xSystemCallStackInfo' ] . ref , 'xSystemCallStackInfo' ) ) || { } ;
@@ -840,6 +845,18 @@ export class RTOSFreeRTOS extends RTOSCommon.RTOSBase {
840845 }
841846 }
842847
848+ // (...) However, when that task returns to a RUNNING state,
849+ // pulTaskStack gets zeroed and the only way to get a stack top that
850+ // bears any resemblance to reality is to read directly from the stack
851+ // pointer register. Note that this can still have surprising results if
852+ // the program is halted in an ISR or system call.
853+ if ( threadRunning ) {
854+ const taskSP = await this . getStackPointerRegVal ( frameId ) ;
855+ if ( taskSP !== undefined ) {
856+ return taskSP ;
857+ }
858+ }
859+
843860 if ( ! ( 'ulContext' in xMPUSettings ) ) {
844861 return undefined ;
845862 }
0 commit comments