News:

Let's find out together what makes a PIC Tick!

Main Menu

Global Dim X as Byte Shared

Started by JonW, Feb 20, 2024, 12:49 PM

Previous topic - Next topic

JonW





Proc AD9833_SetFreqChan(pChan As AD9833_bChannel)
Global Dim AD9833_bChannel As Byte Shared                               ' Holds the channel for procedure parameters

    Select pChan
        Case 0
            AD9833_wControl.cAD9833_FSelect_Bit = 0
        Case 1
            AD9833_wControl.cAD9833_FSelect_Bit = 1
        Case Else
            ExitProc
    EndSelect
    AD9833_WriteCtrlReg(AD9833_wControl)
EndProc




Is this something I have missed, or is a new feature where global variables can be mapped into a Procedure without using more RAM?

Global Dim AD9833_bChannel As Byte Shared                               ' Holds the channel for procedure parameters

top204

#1
Quoteor is a new feature where global variables can be mapped into a Procedure without using more RAM?

Exactly Jon. :-)

The new Global directive allows a variable within a procedure to be declared as a global type, seen by all, and not a local type only seen by the procedure it is created within. It can be created as Shared or not Shared.

It also allows global variables to only be created if a procedure is called, and if a different procedure is called with the same Global declaration, or multiple procedures are called also creating the global variable, the Shared directive will not cause a duplicate variable error, because they "are" the same variable, sharing the same RAM position. All very, very handy. :-)

The Shared directive allows variables to use the same name and type, so if they are declared in other places, they will share the same RAM position. I saw this type of mechanism in an excellent C compiler (no longer with us) for the early microcontrollers with very little RAM many, many years ago, and thought "that's a good idea", so I added it to test things when I first wrote the compiler for the devices that had a few 10s of bytes of RAM space.

So the Shared directive has been in the compiler from day one, all of those years ago, because I used them for development purposes, but they were not 100% working. However, with procedures, they come in very, very handy because global variables can be shared as parameters or returns, or just shared as globals, so I worked on them to make them suitable for users as well and made them more reliable and give error messages if not used correctly etc... So instead of the compiler always choosing RAM slots, the user can as well and this is better for space and efficiency because RAM comes in different flavours on 8-bit PIC microcontrollers.

I'm busy writing a section in the manuals for the Global and Shared directives. But essentially, when Shared, the same global variable name can be used, as long it is designated exactly as the same type, and if it is an array or String it must be the same type and the same length, otherwise, an error message will be given because they will not be able to share the same RAM position/s.

JonW

Ah get it.  This is pretty funky, especially if you are accessing and manipulating global arrays or want a software stack that multiple procedures can access. I have loads of libraries that can be streamlined now, this will simplify the passed and returned data naming and the RAM positioning.

Can these global variables also be heaped at the top of Ram?


top204

#3
Yes. Shared variables can be created to be placed at the top of RAM (above normally created variables) with the Heap directive. Or the beginning of RAM with the Access directive. For example:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstrate the placement of Global Shared variables
' Written for the Positron8 compiler by Les Johnson.
'
    Device = 18F25K20                                                                   ' Tell the compiler what device to compile for
    Declare Xtal = 16                                                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
'
' Create any Global variables for the demo here
'
    Dim Global_tSharedBit   As Bit Shared
    Dim Global_bSharedByte  As Byte Shared
    Dim Global_wSharedWord  As Word Access Shared
    Dim Global_lSharedLong  As Long Shared
    Dim Global_dSharedDWord As Dword Heap Shared
    Dim Global_fSharedFloat As Float Heap Shared

    Dim Global_bSharedByteArray[10]  As Byte Shared
    Dim Global_wSharedWordArray[10]  As Word Shared
    Dim Global_lSharedLongArray[10]  As Long Shared
    Dim Global_dSharedDWordArray[10] As Dword Heap Shared
    Dim Global_fSharedFloatArray[10] As Float Heap Shared
    Dim Global_fSharedString         As String * 10 Heap Shared

'-------------------------------------------------------------------------
' The main program starts here
'
Main:
    Global_lSharedLong = Test_Proc(123)

'-------------------------------------------------------------------------
' A test procedure for shared global variables
'
Proc Test_Proc(pParam1 As Global_bSharedByte), Global_wSharedWord
Global Dim Global_tSharedBit   As Bit Shared
Global Dim Global_bSharedByte  As Byte Shared
Global Dim Global_wSharedWord  As Word Access Shared
Global Dim Global_lSharedLong  As Long Shared
Global Dim Global_dSharedDWord As Dword Heap Shared
Global Dim Global_fSharedFloat As Float Heap Shared

Global Dim Global_bSharedByteArray[10]  As Byte Shared
Global Dim Global_wSharedWordArray[10]  As Word Shared
Global Dim Global_lSharedLongArray[10]  As Long Shared
Global Dim Global_dSharedDWordArray[10] As Dword Heap Shared
Global Dim Global_fSharedFloatArray[10] As Float Heap Shared
Global Dim Global_fSharedString         As String * 10 Heap Shared
EndProc

And the assembler code RAM placements are:

; BIT HOLDER VARIABLES
_B__VR1 equ 0x00
; USER ACCESS RAM VARIABLES
Global_wSharedWord equ 0x01
Global_wSharedWordH equ 0x02
; STANDARD VARIABLES
Global_bSharedByte equ 0x03
Global_lSharedLong equ 0x04
Global_lSharedLongH equ 0x05
Global_lSharedLongHH equ 0x06
Global_bSharedByteArray equ 0x07
variable Global_bSharedByteArray#0=0x07,Global_bSharedByteArray#1=0x08,Global_bSharedByteArray#2=0x09,Global_bSharedByteArray#3=0x0A
variable Global_bSharedByteArray#4=0x0B,Global_bSharedByteArray#5=0x0C,Global_bSharedByteArray#6=0x0D,Global_bSharedByteArray#7=0x0E
variable Global_bSharedByteArray#8=0x0F,Global_bSharedByteArray#9=0x10
Global_wSharedWordArray equ 0x11
Global_wSharedWordArrayH equ 0x12
variable Global_wSharedWordArray#0=0x11,Global_wSharedWordArray#0H=0x12,Global_wSharedWordArray#1=0x13,Global_wSharedWordArray#1H=0x14
variable Global_wSharedWordArray#2=0x15,Global_wSharedWordArray#2H=0x16,Global_wSharedWordArray#3=0x17,Global_wSharedWordArray#3H=0x18
variable Global_wSharedWordArray#4=0x19,Global_wSharedWordArray#4H=0x1A,Global_wSharedWordArray#5=0x1B,Global_wSharedWordArray#5H=0x1C
variable Global_wSharedWordArray#6=0x1D,Global_wSharedWordArray#6H=0x1E,Global_wSharedWordArray#7=0x1F,Global_wSharedWordArray#7H=0x20
variable Global_wSharedWordArray#8=0x21,Global_wSharedWordArray#8H=0x22,Global_wSharedWordArray#9=0x23,Global_wSharedWordArray#9H=0x24
Global_lSharedLongArray equ 0x25
Global_lSharedLongArrayH equ 0x26
Global_lSharedLongArrayHH equ 0x27
variable Global_lSharedLongArray#0=0x25,Global_lSharedLongArray#0H=0x26,Global_lSharedLongArray#0HH=0x27,Global_lSharedLongArray#1=0x28
variable Global_lSharedLongArray#1H=0x29,Global_lSharedLongArray#1HH=0x2A,Global_lSharedLongArray#2=0x2B,Global_lSharedLongArray#2H=0x2C
variable Global_lSharedLongArray#2HH=0x2D,Global_lSharedLongArray#3=0x2E,Global_lSharedLongArray#3H=0x2F,Global_lSharedLongArray#3HH=0x30
variable Global_lSharedLongArray#4=0x31,Global_lSharedLongArray#4H=0x32,Global_lSharedLongArray#4HH=0x33,Global_lSharedLongArray#5=0x34
variable Global_lSharedLongArray#5H=0x35,Global_lSharedLongArray#5HH=0x36,Global_lSharedLongArray#6=0x37,Global_lSharedLongArray#6H=0x38
variable Global_lSharedLongArray#6HH=0x39,Global_lSharedLongArray#7=0x3A,Global_lSharedLongArray#7H=0x3B,Global_lSharedLongArray#7HH=0x3C
variable Global_lSharedLongArray#8=0x3D,Global_lSharedLongArray#8H=0x3E,Global_lSharedLongArray#8HH=0x3F,Global_lSharedLongArray#9=0x40
variable Global_lSharedLongArray#9H=0x41,Global_lSharedLongArray#9HH=0x42
; HEAP VARIABLES
Global_dSharedDWord equ 0x43
Global_dSharedDWordH equ 0x44
Global_dSharedDWordHH equ 0x45
Global_dSharedDWordHHH equ 0x46
Global_fSharedFloat equ 0x47
Global_fSharedFloatH equ 0x48
Global_fSharedFloatHH equ 0x49
Global_fSharedFloatHHH equ 0x4A
Global_dSharedDWordArray equ 0x4B
Global_dSharedDWordArrayH equ 0x4C
Global_dSharedDWordArrayHH equ 0x4D
Global_dSharedDWordArrayHHH equ 0x4E
variable Global_dSharedDWordArray#0=0x4B,Global_dSharedDWordArray#0H=0x4C,Global_dSharedDWordArray#0HH=0x4D,Global_dSharedDWordArray#0HHH=0x4E
variable Global_dSharedDWordArray#1=0x4F,Global_dSharedDWordArray#1H=0x50,Global_dSharedDWordArray#1HH=0x51,Global_dSharedDWordArray#1HHH=0x52
variable Global_dSharedDWordArray#2=0x53,Global_dSharedDWordArray#2H=0x54,Global_dSharedDWordArray#2HH=0x55,Global_dSharedDWordArray#2HHH=0x56
variable Global_dSharedDWordArray#3=0x57,Global_dSharedDWordArray#3H=0x58,Global_dSharedDWordArray#3HH=0x59,Global_dSharedDWordArray#3HHH=0x5A
variable Global_dSharedDWordArray#4=0x5B,Global_dSharedDWordArray#4H=0x5C,Global_dSharedDWordArray#4HH=0x5D,Global_dSharedDWordArray#4HHH=0x5E
variable Global_dSharedDWordArray#5=0x5F,Global_dSharedDWordArray#5H=0x60,Global_dSharedDWordArray#5HH=0x61,Global_dSharedDWordArray#5HHH=0x62
variable Global_dSharedDWordArray#6=0x63,Global_dSharedDWordArray#6H=0x64,Global_dSharedDWordArray#6HH=0x65,Global_dSharedDWordArray#6HHH=0x66
variable Global_dSharedDWordArray#7=0x67,Global_dSharedDWordArray#7H=0x68,Global_dSharedDWordArray#7HH=0x69,Global_dSharedDWordArray#7HHH=0x6A
variable Global_dSharedDWordArray#8=0x6B,Global_dSharedDWordArray#8H=0x6C,Global_dSharedDWordArray#8HH=0x6D,Global_dSharedDWordArray#8HHH=0x6E
variable Global_dSharedDWordArray#9=0x6F,Global_dSharedDWordArray#9H=0x70,Global_dSharedDWordArray#9HH=0x71,Global_dSharedDWordArray#9HHH=0x72
Global_fSharedFloatArray equ 0x73
Global_fSharedFloatArrayH equ 0x74
Global_fSharedFloatArrayHH equ 0x75
Global_fSharedFloatArrayHHH equ 0x76
variable Global_fSharedFloatArray#0=0x73,Global_fSharedFloatArray#0H=0x74,Global_fSharedFloatArray#0HH=0x75,Global_fSharedFloatArray#0HHH=0x76
variable Global_fSharedFloatArray#1=0x77,Global_fSharedFloatArray#1H=0x78,Global_fSharedFloatArray#1HH=0x79,Global_fSharedFloatArray#1HHH=0x7A
variable Global_fSharedFloatArray#2=0x7B,Global_fSharedFloatArray#2H=0x7C,Global_fSharedFloatArray#2HH=0x7D,Global_fSharedFloatArray#2HHH=0x7E
variable Global_fSharedFloatArray#3=0x7F,Global_fSharedFloatArray#3H=0x80,Global_fSharedFloatArray#3HH=0x81,Global_fSharedFloatArray#3HHH=0x82
variable Global_fSharedFloatArray#4=0x83,Global_fSharedFloatArray#4H=0x84,Global_fSharedFloatArray#4HH=0x85,Global_fSharedFloatArray#4HHH=0x86
variable Global_fSharedFloatArray#5=0x87,Global_fSharedFloatArray#5H=0x88,Global_fSharedFloatArray#5HH=0x89,Global_fSharedFloatArray#5HHH=0x8A
variable Global_fSharedFloatArray#6=0x8B,Global_fSharedFloatArray#6H=0x8C,Global_fSharedFloatArray#6HH=0x8D,Global_fSharedFloatArray#6HHH=0x8E
variable Global_fSharedFloatArray#7=0x8F,Global_fSharedFloatArray#7H=0x90,Global_fSharedFloatArray#7HH=0x91,Global_fSharedFloatArray#7HHH=0x92
variable Global_fSharedFloatArray#8=0x93,Global_fSharedFloatArray#8H=0x94,Global_fSharedFloatArray#8HH=0x95,Global_fSharedFloatArray#8HHH=0x96
variable Global_fSharedFloatArray#9=0x97,Global_fSharedFloatArray#9H=0x98,Global_fSharedFloatArray#9HH=0x99,Global_fSharedFloatArray#9HHH=0x9A
Global_fSharedString equ 0x9B
variable Global_fSharedString#0=0x9B,Global_fSharedString#1=0x9C,Global_fSharedString#2=0x9D,Global_fSharedString#3=0x9E
variable Global_fSharedString#4=0x9F,Global_fSharedString#5=0xA0,Global_fSharedString#6=0xA1,Global_fSharedString#7=0xA2
variable Global_fSharedString#8=0xA3,Global_fSharedString#9=0xA4,Global_fSharedString#10=0xA5
; ALIAS VARIABLES
#define __HRSOUT1_PORT PORTC
#define __HRSOUT_PORT PORTC
#define __HRSOUT1_PORT_PIN PORTC,6
#define __HRSOUT_PORT_PIN PORTC,6
#define __HRSIN1_PORT PORTC
#define __HRSIN_PORT PORTC
#define __HRSIN1_PORT_PIN PORTC,7
#define __HRSIN_PORT_PIN PORTC,7
#define Global_tSharedBit _B__VR1,0
#define Test_ProcpParam1 Global_bSharedByte
#define Test_ProcResult Global_wSharedWord
#define Test_ProcResultH Global_wSharedWordH

There are some limitations to the Shared directive, such as casting, aliasing, and addressing, but I am working on them when I get a chance too. However, variable handling is a very complex part of the compiler, so it is something I cannot just jump into and add quickly, especially with casting and addressing because the RAM placements that the compiler performs is dynamic, and one mis-calculation or change without thorough planning can cause variables to be mis-aligned and cause havoc with a program's operation. That's one of the reasons I made the assembler code's RAM assignments nice and clear, so I could see their placements easily, and they are very easy to understand and follow.

I still have to get into the Positron16 compiler and make the Shared and Heap directives more refined in it as well, but the 16-bit devices do not have the same requirements as the 8-bit devices have with RAM, and the Positron16 compiler is fully dynamic with the RAM placements on the 16-bit devices, and they do have boundary limitations that can actually waste RAM if some variable types are placed on a 16-bit boundary. So I will work on them when I get into Positron16 and correct some of the, possible, anomalies in it.

JonW

#4
If you declare the variable at the start of the program or globally at the start of an Include file as a header, why do you need to add the same declaration within each procedure block as above? 

trastikata

Quote from: JonW on Feb 21, 2024, 08:41 AMIf you declare the variable at the start of the program or globally at the start of an Include file as a header, why do you need to add the same declaration within each procedure block as above? 

I'd guess because procedures are using own internal variables and by declaring it within every procedure the same global variable (or RAM space) will be used for the given procedure.

JonW

I can understand that if the declaration is within the proc itself, why then declare globally, as in the above example, that also declares in each procedure?  In the AD9833 example, the declaration was not in the main body of the code but only within the procs. 

I ran a test; it doesn't need to be located in both areas.  If declared at the start and has no ACCESS or HEAP setting, then the variable is mapped at the start of ram; if declared in the PROC and not in the main code, it's still declared but placed higher as the main code variables are stored first.

I guess it is just an example to show that it can be declared in either location. However, the user needs to be careful as declaring in the PROC and using it in the main body could cause issues if the procedures are not called and the declaration of the variable is only in the procedure.

Nice feature!

top204

#7
Within a library file, Global variables will be created, regardless if they are used or not if they are Dimed at the beginning of the listing. So adding Global variables inside a procedure will mean the Global variables are only ever created if the procedures using them are also used in the program. However, if one of the procedures is not used in a program, and that procedure happens to be the one that creates the Global variables, it will mean the variable/s have not been created, so give errors for the variables being missing. In general libraries, the global variables can be created in an initialisation procedure, as long as it is always called, but if used as parameter aliasing, they must always be in the procedure that is using them, just to make sure. Hence "Shared" variables.

It also means that variables can be shared between procedures as parameters or returns or just variables that a few procedures need to use between them, and passing them as a parameter is a waste of RAM and code space, even when passed as ByRef, because the address has to be passed, then all the mnemonics needed to access them indirectly when they are assigned or read.

This is something that C users have not quite learned, when writing for smaller microcontrollers and not a stack orientated microprocessor/microcontroller with a true stack and mnemonics specially designed for indirect operations.

JonW

I think we crossed over on emails ;D .

I recently completed a fairly complex project using a mid-range PIC with limited code space & RAM (the only device currently available in moderate volume when we started the project). Once completed, I was asked why it was not coded C and why it took a lot of flak for using a pitiful basic compiler!!.  My initial response was don't underestimate the compiler; there is no chance it will fit in that MCU using a C compiler.  More flak followed..  To pacify the firmware team, I ported less than 50% of the code using a C compiler before the MCU ran out of resources. The firmware team responded that they would have only used C and a much larger MCU at 5x cost or would have said it could not be done in that MCU!




   

trastikata

Quote from: JonW on Feb 21, 2024, 09:59 AMThe firmware team responded that they would have only used C and a much larger MCU at 5x cost or would have said it could not be done in that MCU!

This is the paradox of modern hardware and software ... everything is getting ever more complex just because new generations don't want to study and understand things in their core.

I predict there will come time when young engineers will have no understanding at all how things work but rather will built everything as a LEGO game from already done pieces.

Dompie

Some time ago I was talking about a little problem a young person had and I was talking about the cosine (of the angle). When I asked if he knew what I meant, he said: Yes, that button on my calculator :'(  :'(

Johan

JonW

#11
QuoteI predict there will come a time when young engineers will have no understanding at all of how things work but rather will build everything as a LEGO game from already done pieces.

or use chat GPT....

John Lawton

Ah, you mean like the Arduino?

:)

John

top204

#13
When I look around the internet, I am afraid it has now, mostly, gone beyond the: "Engineers of the Future" part. Real low-level engineers are a rarity now and someone who has been on a course for a few months is actually stated as an "Engineer"! It took me nearly five years to be classed as an engineer when I was serving my time as a TV engineer, and going to college for my city and guilds on electronics every thursday night. Then it took me quite a few years of constant reading and doing, to teach myself logic and computers back in the early 1980s. But fortunately, it came naturally to me thanks to having my lovely Dad's 'curiosity' genes in me, and him teaching me electronics as a boy.

The fact that people now call it "Arduino", instead of what it really is. i.e. C++, tells you things have gone beyond salvation. Even in schools and colleges and universities, people are taught the methods of putting code together by coloured blocks on a screen, and as stated earlier "Just like Lego".

Stephen Moss

Quote from: trastikata on Feb 21, 2024, 11:26 AMI predict there will come time when young engineers will have no understanding at all how things work but rather will built everything as a LEGO game from already done pieces.
Unfortunately that time is already here, a 4 week 2nd year undergraduate project used to require design and building of electronic circuits, programming and mechanical design to create an autonomous guided vehicle, but the electronics appears to have been deemed too difficult so now they just plug pre-designed and built sensor boards into an Arduino and read the output, so no more circuit design or soldering experience or need to know how to read and interpret data sheets.

Instead of sorting it out at college level or teaching them better in the first year the solution appears to be to take the easy option and dumb down, so you end up with students at the end of their third 3rd year with a University degree in Engineering essentially in the bag unable to get an output from a cheap LASER diode because they are pratting about with some obscure voltage regulator circuit they found online that I could not see working anyway ::)
All they needed to do was apply Ohms law and use a dropper resistor from the existing 5V supply they had, took me at most 2 minutes to get it working on a bread board and half of that was spent getting the resistor.