EmbeddedRelated.com
Forums

Replace application at runtime with IAP and boot switch

Started by Anders Hvidgaard Poder July 1, 2012
I am developing a GSM based application using LPC1768 and Red Suite 3.
I use FlashMagic for deployment (not debugging and test, I use a
debugging link directly from Red Suite 3).

The LPC1768 has got 512kbyte Flash. The main application uses about
150kbyte, so I am able to have two complete applications in Flash at
the same time. Initially only one application exist, but the
application is able to load another from GSM into unused Flash using
IAP.

I expect to place the boot application in the first 4k sector. The
configurations in the next two 4k sectors and the applications from
0X0000 3000 - 0x0003 FFFF (application 1) and 0x0004 0000 - 0x0007
FFFF (application 2).

I then want to have the boot application (boot switch) determine which
is the newest application based on the configurations in sector 2 and
3 and jump to the newest application.

I have the following questions:

1. How do we write an application that can move the instruction
pointer to the correct start address and at the same time make sure
the active interrupt vectors in the first 256 bytes work correctly.
Where to move the instruction pointer should be read from the
configurations in sector 2 and 3.

2. How to deploy an application to an address other than 0x0000 0000.
When building the .axf and .hex file it is always deployed to address
0 in the Flash, regardless of whether I deploy with FlashMagic or Red
Suite. How do I change this starting address?

With respect to loading to another start address I have found a
section in the .ld file used by Red Suite which allows to move the
start address, but the .hex file (generated with
arm-none-eabi-objcopy) still indicate an address starting form 0. Also
when I attempt to download using Red Suite with another start address
it fails with a message about not being able to download to another
start address for ELF files.

I have found several references in boot loaders where it simply says:
"Load the application to address xxx", and in IAP I know how to do
that, but not from FlashMagic/Red Suite.

If you are not able to help me directly maybe you know of a company
which would be able to take on the assignment. I have not been able to
find any consulting companies with this level of NXP knowledge. I
asked embedded artists, and they suggested this group. Alternatively
if there is some literature or code examples which might help I would
be very great-full.

Thank you in advance

An Engineer's Guide to the LPC2100 Series

On Mon, Jul 2, 2012 at 4:06 AM, Anders Hvidgaard Poder wrote:

> 1. How do we write an application that can move the instruction
> pointer to the correct start address and at the same time make sure
> the active interrupt vectors in the first 256 bytes work correctly.
> Where to move the instruction pointer should be read from the
> configurations in sector 2 and 3.
>

you can change the address of the instruction vector table with the VTOR
register. it should be on a 1024 byte boundary and must be on a 256 byte
boundary. See the lpc17xx user manual, sections 6.4 and 34.4.3.5.

your stage-2 bootloader can simply jump to any location you choose.. if
you're writing C, use a function pointer.

Usually your bootloader will set VTOR to the start of the application
block, then pull a reset vector out of it and jump to that.
> 2. How to deploy an application to an address other than 0x0000 0000.
> When building the .axf and .hex file it is always deployed to address
> 0 in the Flash, regardless of whether I deploy with FlashMagic or Red
> Suite. How do I change this starting address?
>

I don't know about either of those suites, but with the GNU toolchain I
simply alter the address and length of the rom section in the linker script
and the hex is generated appropriately


Thank you for the reply, it was very helpful. I have found a solution to the first part of the problem, and half of the second.

I had a closer look at the example USB boot loader (http://www.nxp.com/documents/application_note/AN10866.pdf) and found the code for jumping to the main application and more importantly to update the interrupt vector.

Then I discovered it was important to disable the function call SystemInit() from the boot switch application, as this may not be called twice, and should be called by the main application (I think - at least it works).

I then removed the flag from the Settings->MCU Linker->Target->Manage linker script and write the link files (.ld) correctly with the new origin. That worked when I downloaded with Red Suite, but the hex file is still not generated corretly, as far as I can see. The build script for the hex file is:

arm-none-eabi-size ${BuildArtifactFileName};
arm-none-eabi-objcopy -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin ;
checksum -p ${TargetChip} -d ${BuildArtifactFileBaseName}.bin;
arm-none-eabi-objcopy -I binary -O ihex ${BuildArtifactFileBaseName}.bin ${BuildArtifactFileBaseName}.hex

There is a parameter for the arm-none-eabi-objcopy to change the start address, but I have not been able to make it work. Does anyone have any idea how to use the arm-none-eabi-objcopy to generate a hex file with a different origin / start address?

--- In l..., Triffid Hunter wrote:
>
> On Mon, Jul 2, 2012 at 4:06 AM, Anders Hvidgaard Poder wrote:
>
> > 1. How do we write an application that can move the instruction
> > pointer to the correct start address and at the same time make sure
> > the active interrupt vectors in the first 256 bytes work correctly.
> > Where to move the instruction pointer should be read from the
> > configurations in sector 2 and 3.
> > you can change the address of the instruction vector table with the VTOR
> register. it should be on a 1024 byte boundary and must be on a 256 byte
> boundary. See the lpc17xx user manual, sections 6.4 and 34.4.3.5.
>
> your stage-2 bootloader can simply jump to any location you choose.. if
> you're writing C, use a function pointer.
>
> Usually your bootloader will set VTOR to the start of the application
> block, then pull a reset vector out of it and jump to that.
> > 2. How to deploy an application to an address other than 0x0000 0000.
> > When building the .axf and .hex file it is always deployed to address
> > 0 in the Flash, regardless of whether I deploy with FlashMagic or Red
> > Suite. How do I change this starting address?
> > I don't know about either of those suites, but with the GNU toolchain I
> simply alter the address and length of the rom section in the linker script
> and the hex is generated appropriately
>
>

On Tue, Jul 3, 2012 at 7:43 PM, ahpoder wrote:

> Thank you for the reply, it was very helpful. I have found a solution to
> the first part of the problem, and half of the second.
>
> I had a closer look at the example USB boot loader (
> http://www.nxp.com/documents/application_note/AN10866.pdf) and found the
> code for jumping to the main application and more importantly to update the
> interrupt vector.
>
> Then I discovered it was important to disable the function call
> SystemInit() from the boot switch application, as this may not be called
> twice, and should be called by the main application (I think - at least it
> works).
>

fwiw I've had no problems calling it twice in my applications. I think that
it's suggested to not run it twice as it could re-initialise the crystal
oscillator while using that as primary osc. If this is a concern, you could
simply check if the crystal osc and PLL0 is already initialised
appropriately and skip SystemInit if so.

I then removed the flag from the Settings->MCU Linker->Target->Manage
> linker script and write the link files (.ld) correctly with the new origin.
> That worked when I downloaded with Red Suite, but the hex file is still not
> generated corretly, as far as I can see. The build script for the hex file
> is:
>
> arm-none-eabi-size ${BuildArtifactFileName};
> arm-none-eabi-objcopy -O binary ${BuildArtifactFileName}
> ${BuildArtifactFileBaseName}.bin ;
> checksum -p ${TargetChip} -d ${BuildArtifactFileBaseName}.bin;
> arm-none-eabi-objcopy -I binary -O ihex ${BuildArtifactFileBaseName}.bin
> ${BuildArtifactFileBaseName}.hex
>
> There is a parameter for the arm-none-eabi-objcopy to change the start
> address, but I have not been able to make it work. Does anyone have any
> idea how to use the arm-none-eabi-objcopy to generate a hex file with a
> different origin / start address?
>

If you alter the addresses in the hex, then your application will not work
because all your function calls will point to the wrong addresses, and your
initialised variables will be loaded from the wrong place.

The addresses in the hex file come from the locations in the ELF file that
results from final linking. They are defined by your linker script. Alter
where the .text section goes in memory in your linker script to change this.

This MUST be done by the linker, because once it has worked out where
everything goes, it then fills in all the unknown addresses eg for function
calls, flash data, etc. If you want code that can be moved anywhere in
memory, you might like to experiment to see if -fPIC works with these chips.

arm-none-eabi-objdump -h PROJECT.elf -j .text -j .data will show you the
locations. VMA and LMA should be the same as your origin for the .text
section. The LMA for your .data section should be after the end of the
.text section somewhere, and the VMA should be the start of SRAM in your
chip's memory space.

fyi: LMA is the address that data is put in the hex file, VMA is where it
ends up when your application is starting, i.e.; between
(interrupt_vectors->reset)() and main().

Here's some sample output from a project of mine that works perfectly:

Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000826c *00004000 00004000* 00004000 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .data 00000600 *10000000 0000c340* 00010000 2**2
CONTENTS, ALLOC, LOAD, DATA

As you can see, my program is being loaded into 0x4000 to leave room for
the bootloader. There's 1.5k of pre-initialised data that starts off in
flash at 0xC340 but gets copied to 0x10000000 (start of SRAM) before main()
is called.

A couple of lines of the resulting .hex:
:10*4000*0000800010CD400000CB5D0000CD5D0000C1
:10*4010*00CF5D0000D15D0000D35D00000000000016
:10*4020*00000000000000000000000000AD5D000086

show that the addresses in the hex agree with the LMA addresses in the ELF
file.

Here's the relevant section from my linker script:

MEMORY
{
rom (rx) : ORIGIN = 16K, LENGTH = (512K - 16K) /* Bootloader uses first
16Kbytes of flash memory */
/* rom (rx) : ORIGIN = 0, LENGTH = 512K /* for running without
bootloader */
ram (rwx) : ORIGIN = 0x10000000, LENGTH = 32K
ahbb0(rw) : ORIGIN = 0x2007C000, LENGTH = 16K
ahbb1(rw) : ORIGIN = 0x20080000, LENGTH = 16K
}
good luck!


Thank you again for the reply,

I have had a look at the linker script and my script look like this (for the memory portion):

MEMORY
{
/* Define each memory region */
MFlash512 (rx) : ORIGIN = 0x3000, LENGTH = 0x3D000 /* 256k */
RamLoc32 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 32k */
RamAHB32 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x8000 /* 32k */
CANAccFilterRAM (rwx) : ORIGIN = 0x40038000, LENGTH = 0x800 /* 2k */
}

It works just fine when downloading the .axf file via Red Suite 3. There is no .elf file generate, only a .bin file, which is then turned into a .hex file. So the .axf file must contain the correct origin references. I looked at the .map file generated during linking and it is clear to see that the offset is correct included.

There is no .elf file, and the .hex file is generated from the .bin file. I have included the first three lines of the hex file generated:

:1000000000800010013100006931000071310000F2
:10001000793100008131000089310000A257FEEFE4
:10002000000000000000000000000000913100000E

which do not start from 0x3000. It turns out the .axf file is actually an .elf file, and when I execute the objdump on that file I get:

Idx Name Size VMA LMA File off Algn
0 .text 00039d34 00003000 00003000 00003000 2**3
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 000007c8 10000000 0003cd34 00040000 2**2
CONTENTS, ALLOC, LOAD, DATA

which seems perfectly correct. Then I tried using the .axf file as input for the objcopy command generating the .hex file, instead of using the .bin file, and then I get this:

:1030000000800010013100006931000071310000C2
:10301000793100008131000089310000000000009A
:1030200000000000000000000000000091310000DE

Now it works. I am not sure why, but apparently the .bin file do not persist the offset.

I will consider this issue closed, as I now have a functioning prototype and thank you very much for all your help.

--- In l..., Triffid Hunter wrote:
>
> On Tue, Jul 3, 2012 at 7:43 PM, ahpoder wrote:
>
> > Thank you for the reply, it was very helpful. I have found a solution to
> > the first part of the problem, and half of the second.
> >
> > I had a closer look at the example USB boot loader (
> > http://www.nxp.com/documents/application_note/AN10866.pdf) and found the
> > code for jumping to the main application and more importantly to update the
> > interrupt vector.
> >
> > Then I discovered it was important to disable the function call
> > SystemInit() from the boot switch application, as this may not be called
> > twice, and should be called by the main application (I think - at least it
> > works).
> > fwiw I've had no problems calling it twice in my applications. I think that
> it's suggested to not run it twice as it could re-initialise the crystal
> oscillator while using that as primary osc. If this is a concern, you could
> simply check if the crystal osc and PLL0 is already initialised
> appropriately and skip SystemInit if so.
>
> I then removed the flag from the Settings->MCU Linker->Target->Manage
> > linker script and write the link files (.ld) correctly with the new origin.
> > That worked when I downloaded with Red Suite, but the hex file is still not
> > generated corretly, as far as I can see. The build script for the hex file
> > is:
> >
> > arm-none-eabi-size ${BuildArtifactFileName};
> > arm-none-eabi-objcopy -O binary ${BuildArtifactFileName}
> > ${BuildArtifactFileBaseName}.bin ;
> > checksum -p ${TargetChip} -d ${BuildArtifactFileBaseName}.bin;
> > arm-none-eabi-objcopy -I binary -O ihex ${BuildArtifactFileBaseName}.bin
> > ${BuildArtifactFileBaseName}.hex
> >
> > There is a parameter for the arm-none-eabi-objcopy to change the start
> > address, but I have not been able to make it work. Does anyone have any
> > idea how to use the arm-none-eabi-objcopy to generate a hex file with a
> > different origin / start address?
> > If you alter the addresses in the hex, then your application will not work
> because all your function calls will point to the wrong addresses, and your
> initialised variables will be loaded from the wrong place.
>
> The addresses in the hex file come from the locations in the ELF file that
> results from final linking. They are defined by your linker script. Alter
> where the .text section goes in memory in your linker script to change this.
>
> This MUST be done by the linker, because once it has worked out where
> everything goes, it then fills in all the unknown addresses eg for function
> calls, flash data, etc. If you want code that can be moved anywhere in
> memory, you might like to experiment to see if -fPIC works with these chips.
>
> arm-none-eabi-objdump -h PROJECT.elf -j .text -j .data will show you the
> locations. VMA and LMA should be the same as your origin for the .text
> section. The LMA for your .data section should be after the end of the
> .text section somewhere, and the VMA should be the start of SRAM in your
> chip's memory space.
>
> fyi: LMA is the address that data is put in the hex file, VMA is where it
> ends up when your application is starting, i.e.; between
> (interrupt_vectors->reset)() and main().
>
> Here's some sample output from a project of mine that works perfectly:
>
> Sections:
> Idx Name Size VMA LMA File off Algn
> 0 .text 0000826c *00004000 00004000* 00004000 2**3
> CONTENTS, ALLOC, LOAD, READONLY, CODE
> 3 .data 00000600 *10000000 0000c340* 00010000 2**2
> CONTENTS, ALLOC, LOAD, DATA
>
> As you can see, my program is being loaded into 0x4000 to leave room for
> the bootloader. There's 1.5k of pre-initialised data that starts off in
> flash at 0xC340 but gets copied to 0x10000000 (start of SRAM) before main()
> is called.
>
> A couple of lines of the resulting .hex:
> :10*4000*0000800010CD400000CB5D0000CD5D0000C1
> :10*4010*00CF5D0000D15D0000D35D00000000000016
> :10*4020*00000000000000000000000000AD5D000086
>
> show that the addresses in the hex agree with the LMA addresses in the ELF
> file.
>
> Here's the relevant section from my linker script:
>
> MEMORY
> {
> rom (rx) : ORIGIN = 16K, LENGTH = (512K - 16K) /* Bootloader uses first
> 16Kbytes of flash memory */
> /* rom (rx) : ORIGIN = 0, LENGTH = 512K /* for running without
> bootloader */
> ram (rwx) : ORIGIN = 0x10000000, LENGTH = 32K
> ahbb0(rw) : ORIGIN = 0x2007C000, LENGTH = 16K
> ahbb1(rw) : ORIGIN = 0x20080000, LENGTH = 16K
> }
> good luck!
>
>

Are you aware of what a binary file is? It is a pure dump of the bytes that need to be loaded into memory - there is no 'offset' information or anything else. If you want an offset, you have to tell whatever is loading the binary file where to load it...

.axf is ARMs standard name for an Arm eXecutable File. The file format is .elf, but I think it also implies debug information format (DWARF) and EABI.

--- In l..., "ahpoder" wrote:
>
> Thank you again for the reply,
>
> I have had a look at the linker script and my script look like this (for the memory portion):
>
> MEMORY
> {
> /* Define each memory region */
> MFlash512 (rx) : ORIGIN = 0x3000, LENGTH = 0x3D000 /* 256k */
> RamLoc32 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000 /* 32k */
> RamAHB32 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x8000 /* 32k */
> CANAccFilterRAM (rwx) : ORIGIN = 0x40038000, LENGTH = 0x800 /* 2k */
> }
>
> It works just fine when downloading the .axf file via Red Suite 3. There is no .elf file generate, only a .bin file, which is then turned into a .hex file. So the .axf file must contain the correct origin references. I looked at the .map file generated during linking and it is clear to see that the offset is correct included.
>
> There is no .elf file, and the .hex file is generated from the .bin file. I have included the first three lines of the hex file generated:
>
> :1000000000800010013100006931000071310000F2
> :10001000793100008131000089310000A257FEEFE4
> :10002000000000000000000000000000913100000E
>
> which do not start from 0x3000. It turns out the .axf file is actually an .elf file, and when I execute the objdump on that file I get:
>
> Idx Name Size VMA LMA File off Algn
> 0 .text 00039d34 00003000 00003000 00003000 2**3
> CONTENTS, ALLOC, LOAD, READONLY, CODE
> 1 .data 000007c8 10000000 0003cd34 00040000 2**2
> CONTENTS, ALLOC, LOAD, DATA
>
> which seems perfectly correct. Then I tried using the .axf file as input for the objcopy command generating the .hex file, instead of using the .bin file, and then I get this:
>
> :1030000000800010013100006931000071310000C2
> :10301000793100008131000089310000000000009A
> :1030200000000000000000000000000091310000DE
>
> Now it works. I am not sure why, but apparently the .bin file do not persist the offset.
>
> I will consider this issue closed, as I now have a functioning prototype and thank you very much for all your help.
>
> --- In l..., Triffid Hunter wrote:
> >
> > On Tue, Jul 3, 2012 at 7:43 PM, ahpoder wrote:
> >
> > > Thank you for the reply, it was very helpful. I have found a solution to
> > > the first part of the problem, and half of the second.
> > >
> > > I had a closer look at the example USB boot loader (
> > > http://www.nxp.com/documents/application_note/AN10866.pdf) and found the
> > > code for jumping to the main application and more importantly to update the
> > > interrupt vector.
> > >
> > > Then I discovered it was important to disable the function call
> > > SystemInit() from the boot switch application, as this may not be called
> > > twice, and should be called by the main application (I think - at least it
> > > works).
> > >
> >
> > fwiw I've had no problems calling it twice in my applications. I think that
> > it's suggested to not run it twice as it could re-initialise the crystal
> > oscillator while using that as primary osc. If this is a concern, you could
> > simply check if the crystal osc and PLL0 is already initialised
> > appropriately and skip SystemInit if so.
> >
> > I then removed the flag from the Settings->MCU Linker->Target->Manage
> > > linker script and write the link files (.ld) correctly with the new origin.
> > > That worked when I downloaded with Red Suite, but the hex file is still not
> > > generated corretly, as far as I can see. The build script for the hex file
> > > is:
> > >
> > > arm-none-eabi-size ${BuildArtifactFileName};
> > > arm-none-eabi-objcopy -O binary ${BuildArtifactFileName}
> > > ${BuildArtifactFileBaseName}.bin ;
> > > checksum -p ${TargetChip} -d ${BuildArtifactFileBaseName}.bin;
> > > arm-none-eabi-objcopy -I binary -O ihex ${BuildArtifactFileBaseName}.bin
> > > ${BuildArtifactFileBaseName}.hex
> > >
> > > There is a parameter for the arm-none-eabi-objcopy to change the start
> > > address, but I have not been able to make it work. Does anyone have any
> > > idea how to use the arm-none-eabi-objcopy to generate a hex file with a
> > > different origin / start address?
> > >
> >
> > If you alter the addresses in the hex, then your application will not work
> > because all your function calls will point to the wrong addresses, and your
> > initialised variables will be loaded from the wrong place.
> >
> > The addresses in the hex file come from the locations in the ELF file that
> > results from final linking. They are defined by your linker script. Alter
> > where the .text section goes in memory in your linker script to change this.
> >
> > This MUST be done by the linker, because once it has worked out where
> > everything goes, it then fills in all the unknown addresses eg for function
> > calls, flash data, etc. If you want code that can be moved anywhere in
> > memory, you might like to experiment to see if -fPIC works with these chips.
> >
> > arm-none-eabi-objdump -h PROJECT.elf -j .text -j .data will show you the
> > locations. VMA and LMA should be the same as your origin for the .text
> > section. The LMA for your .data section should be after the end of the
> > .text section somewhere, and the VMA should be the start of SRAM in your
> > chip's memory space.
> >
> > fyi: LMA is the address that data is put in the hex file, VMA is where it
> > ends up when your application is starting, i.e.; between
> > (interrupt_vectors->reset)() and main().
> >
> > Here's some sample output from a project of mine that works perfectly:
> >
> > Sections:
> > Idx Name Size VMA LMA File off Algn
> > 0 .text 0000826c *00004000 00004000* 00004000 2**3
> > CONTENTS, ALLOC, LOAD, READONLY, CODE
> > 3 .data 00000600 *10000000 0000c340* 00010000 2**2
> > CONTENTS, ALLOC, LOAD, DATA
> >
> > As you can see, my program is being loaded into 0x4000 to leave room for
> > the bootloader. There's 1.5k of pre-initialised data that starts off in
> > flash at 0xC340 but gets copied to 0x10000000 (start of SRAM) before main()
> > is called.
> >
> > A couple of lines of the resulting .hex:
> > :10*4000*0000800010CD400000CB5D0000CD5D0000C1
> > :10*4010*00CF5D0000D15D0000D35D00000000000016
> > :10*4020*00000000000000000000000000AD5D000086
> >
> > show that the addresses in the hex agree with the LMA addresses in the ELF
> > file.
> >
> > Here's the relevant section from my linker script:
> >
> > MEMORY
> > {
> > rom (rx) : ORIGIN = 16K, LENGTH = (512K - 16K) /* Bootloader uses first
> > 16Kbytes of flash memory */
> > /* rom (rx) : ORIGIN = 0, LENGTH = 512K /* for running without
> > bootloader */
> > ram (rwx) : ORIGIN = 0x10000000, LENGTH = 32K
> > ahbb0(rw) : ORIGIN = 0x2007C000, LENGTH = 16K
> > ahbb1(rw) : ORIGIN = 0x20080000, LENGTH = 16K
> > }
> >
> >
> > good luck!
> >
> >
> >
>

--- In l..., "thenewfallguy" wrote:
>
> Are you aware of what a binary file is? It is a pure dump of the bytes that need to be loaded into memory - there is no 'offset' information or anything else. If you want an offset, you have to tell whatever is loading the binary file where to load it...
>

..which is why, for my bootloader, (which can load either of two banks of flash with multiple sections), I use S-record images, not binaries.

Rgds,
Martin

-> > ..which is why, for my bootloader, (which can load either of two banks of flash with multiple sections), I use S-record images, not binaries.
>

Which, for completeness, I should add that it's not trivial. IAP can only blow 256/512/1024/4096 bytes at a time and the containing sector must have been erased/prepared first. In unfortunate section-placement cases, this can mean it is not directly possible to blow later data without destroying previously-written data. For this reason, it's very important that section-placements to not overlap IAP sector boundaries!

So far, I've 'got away with it' by buffering 2048 bytes in RAM until such time that an S-record is parsed that wants to write outside the buffer - I then burn in the buffer and start on the new 2048-byte section.

If an S-record ever turns up that wants to overwrite a previously-blown buffer, I'm stuft:(

Rgds,
martin

On Wed, Jul 4, 2012 at 10:46 PM, ahpoder wrote:
> There is no .elf file, and the .hex file is generated from the .bin file.

ah there's your problem, binary is just the raw data, no information
about where in memory it's supposed to go, so of course when you turn
it back into hex it'll be placed at address 0.

you need to generate your hex from the linked object file instead

> Then I tried using the .axf file as input for the objcopy command generating the .hex file, instead of using the .bin file, and then I get this:
> Now it works.

bingo!

> I am not sure why, but apparently the .bin file do not persist the offset.

no they don't. the binary is probably the poorest source of
information you can get, quite a lot must be thrown away to make it.
the elf (or axf or whatever) is the best one to keep and base all your
operations around since it has the most information :)

> I will consider this issue closed, as I now have a functioning prototype and thank you very much for all your help.

you're welcome!