Unimplemented memory location error with PIC16F877 and an array

Started by broderic, Mar 11, 2024, 06:51 AM

Previous topic - Next topic

broderic

Hello.
When I run in Proteus the following Positron code, I have this error:

[PIC16 MEMORY] PC=0x0058. Attempt to read unimplemented memory location 0x0187 ignored. [U1]
[PIC16 MEMORY] PC=0x0058. Attempt to write unimplemented memory location 0x0187 with 0x80 ignored. [U1]
[PIC16 MEMORY] PC=0x005A. Attempt to read unimplemented memory location 0x0107 ignored. [U1]

'****************************************************************
'*  Name    : Receive oregon simu v21.BAS                       *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2023 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 09/03/2024                                        *
'*  Version : 1.0                                               *
'*  Notes   : Simulation version(see same name in Proteus)      *
'*          : Algorithm of "Oregon Scientific RF Protocol"      *
'*          : for THGN132N sensor(V2.1 prot.)                   *
'****************************************************************
    Include "Proton_20.Inc"         'Configure ports for Positron8 board
    On_Hardware_Interrupt GoTo ISR_Handler'Point to interrupt handler
    'Allocate RAM
    Dim Buffer[MaxBuffer] As Byte
    Dim DataOut[3] As Byte          'Data out array.
    Dim PulseWidth As Byte
    Dim I As Byte=0                 'Data byte counter.
    Dim last As Byte
    Dim LastPulseWidth As Byte
    Dim State As Byte = 0x00
    Dim Oldstate As Byte = 0x00
    Dim Count As Byte               'Timer0 overflow counter.
    Dim Count1 As Byte              'Half-time counter.
    Symbol MaxBuffer=200
    Dim BufferUpTo As Byte =0
    Dim UpToMinusOne As Byte
   
    Dim PreambleCount As Byte=0
'------------------------------------------------------------------------
' The main program starts here.
Main:
    DelayMS 21                      ' Wait for things to stabilise.
    TRISC = %11011111               ' Set PORTC I/O.   
    'Setup Timer0.
    OPTION_REGbits_PS2=0            ' 1:2 prescaler.
    OPTION_REGbits_PS1=0
    OPTION_REGbits_PS0=0
    OPTION_REGbits_PSA=0
    OPTION_REGbits_T0CS=0
    OPTION_REGbits_T0SE=0 

     Proc MyProc(LowPulseWidth As Byte, HighPulseWidth As Byte)
          If BufferUpTo <>0 Then
              last=Buffer[BufferUpTo-1]
          Else
               last="0"     
          EndIf 
          If HighPulseWidth>=6 And HighPulseWidth<=27 Then
               If HighPulseWidth>=15 Then
                    Buffer[BufferUpTo]="0"
                    Inc BufferUpTo
                    Buffer[BufferUpTo]="1"
                    Inc BufferUpTo
               Else
                    If BufferUpTo<>0 And LowPulseWidth>=6 And LowPulseWidth<17 Then
                         Buffer[BufferUpTo]=last
                         Inc BufferUpTo
                    ElseIf LowPulseWidth>=17 And LowPulseWidth<28 Then
                         Buffer[BufferUpTo]= "0"
                         Inc BufferUpTo
                    Else
                         If BufferUpTo>10 Then
                         EndIf
                         BufferUpTo=0
                    EndIf
               EndIf
           EndIf   
     EndProc

Again:
    'Setup the interrupt.
    INTCONbits_T0IE = 1     'Enable the Timer0 overflow interrupt.
    INTCONbits_PEIE = 1     'Enable peripheral interrupts.
    INTCONbits_GIE = 1      'Enable all interrupts.
    INTCONbits_T0IF=0       'Clear Timer0 flag.
    TMR0=171                'Initial. Timer0 to inter.every 151*0.2*2+x=200us.
    Count1=0                'First transit. occurs at the end of synchr.space.
Start:
   
 GoTo Start

ISR_Handler:
    Context Save
    If INTCONbits_T0IF = 1 Then     'Timer0 overf.triggered the interrupt?
     'Oldstate=State
     State=PinGet 23               'Value in RC7(RA0=1...RC7=23)in Mybyte
     Inc Count
     
     
     If State<>Oldstate Then       'Transition occurred.
        PulseWidth=Count
        'Inc Count1
        Count=0
        If State = 0x00 Then
           MyProc(LastPulseWidth, PulseWidth)
        EndIf
       
        LastPulseWidth=PulseWidth 
        If PulseWidth>=12 And  PulseWidth<=27 Then
          Inc PreambleCount
        Else
          PreambleCount=0
        EndIf
     
        If PreambleCount=32 Then
          PreambleCount=0
        EndIf       
        Oldstate=State 
      EndIf 
    EndIf
    INTCONbits_T0IF = 0
    TMR0=171
    Context Restore                 'Exit the interrupt, restoring registers
   

It compiles properly.
But I have this error if array dimension is more than 133 elements.
The error occurs at the beginning of ISR, when executing line State=PinGet 23.
It seems as it is a bank switching problem, isn't it?

Any suggestion to overcome this?

Thank you very much for your attention.
Regards

RGV250

Hi,
I would say this is an issue with the VSM, have you tried it with real hardware. I would post the query on the Labcenter forum.

Regards,
Bob

top204

Change the line:

State = PinGet 23

to

State = PORTC.7

Because the PinGet command uses indirect access to read the Port's address, then get the bit's state.

With the, now very obsolete, standard 14-bit core devices and their fragmented RAM and their RAM indirect method that only works in 8-bits, the IRP bit of the STATUS SFR needs to be altered, and it has to be dynamically changed for indirect access above address 255, then again for an address below 256. The compiler tries its damnest to keep track of teh IRP state, but, in this case, has lost track of it. So this is causing the problem, because the compiler has lost track of its last state bacuse it is in an interrupt that can be called from anywhere, withthe IRP bit in any state. This is probably because of the method I had to implement to make larger arrays possible with the very fragmented RAM in standard 14-bit core devices, that also dynamically changes the IRP bit for the required element of an array, because it may be in any one of the 4 fragmented RAM banks, above or below the 255 byte address.

Unfortunately, I am going to have to restrict some more commands when used on the very old devices because the, more recent, commands were designed for the enhanced 14-bit core types and 18F types, and I have made the assumption they would be OK for the standard 14-bit core devices as well, but an incorrect assumption, based on things I had forgotten I had to jump through hoops with to get working in the first place with these dreadful 14-bit core devices from long ago. :-)

Also within your code... I would not recommend calling a procedure from within an interrupt on standard 14-bit core devices, because they have such a small hardware call stack, and the interrupt itself places a value on that, then the compiler looks what is used in the procedure and has to save everything in there are well, which takes up more precious RAM on these old devices.

My one recommendation would be to go for an enhanced 14-bit core device or an 18F device, because they have a linear mechanism for indirect access to RAM, and no bit manipulations or tracking need to be done by the compiler.

broderic

Thanks Bob for your attention.
Thank you very much Les, for your very kind and exhaustive explanation.
Always some interesting to learn with this nice compiler :)
I'll follow your suggestion: I was doubtful too, if it was admitted to call,unpunished, a procedure from an ISR, but I did it, since I have a lot of job to do when the state of the PIN changed, so I didn't know if to leave the job in the ISR or where.

In the morning I simply tried to overcome the issue of "not implemented memory location" and, looking at the data sheet, I saw that PORTB has not unimplemented memory location in bank 2 and 3.
So I changed in State = PinGet 15 (that is PORTB.7).
So I avoided the error of non implemented memory location and the Proteus simulation worked properly with the 200 elements array..
It was just a way to go on while waiting for your explanation of the real cause...

Kind Regards.


top204

Just to let you know broderic, that I have corrected the anomaly with the GetPin command on standard 14-bit core devices, and optimised it for all devices so it does not always need to use indirect access to RAM if a constant or Port.Pin is used as its parameter, and the assembler code is a simple reading of a Port.Pin in their case.

Thanks for spotting the anomaly that will only become a problem in very few cases where the GetPin command has to be 'just' in the wrong spot in the code listing in an interrupt and between 'some' other random commands or expressions that also access RAM indirectly using the FSR register on standard 14-bit core devices with more that 2 banks of RAM. :-) It was a right bugger to find out what was, sometimes, causing the problem, but an easy fix once found.

It also fixes an anomaly that someone brought up a few months ago about the IRP bit within interrupts on standard 14-bit core devices, and I just could not see a problem without any code supplied, but with your code I could see the problem and this fix also fixes that anomaly, because your context save array is in high RAM because of the busyness (is that a real word?) of the code within the interrupt, and the large array.

I will be issuing a corrections update to the Positron8 compiler ASAP. Note that the update is purely for anomaly corrections and will not add new devices. That is why one is called an 'upgrade' and the other an 'update'. :-)

broderic

Thank you so much for your additional work!
All the best.
Regards.

top204

For now, and until I can get the update ready, just place the line:

STATUSbits_IRP = 0

When the interrupt first starts, and the next line down from its Save Context directive. This will reset the indirect RAM position to low RAM, so the commands know where they are starting from. So the beginning of the interrupt code will look like:

    Context Save
    STATUSbits_IRP = 0
    If INTCONbits_T0IF = 1 Then

It can be left in place because it will not disturb any future corrections, and actually does manually what one of the corrections will do automatically, if it sees its context being loaded into a high RAM area for saving. i.e. With more RAM used in a program.