Skip to content

//go:section pragma #1759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 24, 2021
Merged

//go:section pragma #1759

merged 2 commits into from
Jun 24, 2021

Conversation

aykevl
Copy link
Member

@aykevl aykevl commented Mar 30, 2021

This PR adds a new pragma for functions and globals to set the
section name. This can be useful to place a function or global in a
special device specific section, for example:

  • Functions may be placed in RAM to make them run faster, or in flash
    (if RAM is the default) to not let them take up RAM.
  • DMA memory may only be placed in a special memory area.
  • Some RAM may be faster than other RAM, and some globals may be
    performance critical thus placing them in this special RAM area can
    help.
  • Some (large) global variables may need to be placed in external RAM,
    which can be done by placing them in a special section.

To use it, you have to place a function or global in a special section,
for example:

//go:section .externalram
var externalRAMBuffer [1024]byte

This can then be placed in a special section of the linker script, for
example something like this:

.bss.extram (NOLOAD) : {
    *(.externalram)
} > ERAM

This PR also adds some testing for pragmas, for regression testing.

@aykevl
Copy link
Member Author

aykevl commented Mar 30, 2021

@ardnew @kenbell @sago35 this may be of interest.

@kenbell
Copy link
Member

kenbell commented Mar 30, 2021

nice!

@sago35
Copy link
Member

sago35 commented Apr 5, 2021

I'll try it later.

@kenbell
Copy link
Member

kenbell commented Apr 6, 2021

I've updated the 'persistent ram' prototype to use this mechanism: #1715

Seems to work fine.

@deadprogram
Copy link
Member

@aykevl one more merge conflict needs to be resolved, please.

@sago35
Copy link
Member

sago35 commented Apr 13, 2021

@aykevl

The following source code worked fine.
When writing to targets/arm.ld, I would like to name it something like the beginning of .data.
But I don't know what name would be appropriate.

/* targets/arm.ld */

    /* Globals with initial value */
    .data :
    {
        . = ALIGN(4);
        _sdata = .;        /* used by startup code */
        *(.canram)
        *(.canram.*)
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        _edata = .;        /* used by startup code */
    } >RAM AT>FLASH_TEXT
//go:section .canram
//go:align 4
var CANRxFifo [2][1024]byte

//go:section .canram
//go:align 4
var CANTxFifo [2][1024]byte

//go:section .canram
//go:align 4
var CANEvFifo [2][1024]byte

@deadprogram
Copy link
Member

@aykevl reminder this has merge conflict that needs resolution, please.

@sago35
Copy link
Member

sago35 commented Apr 26, 2021

With the following code, I was able to place the variable dummy in .text.
There is a PR to put tinyfont data in the const area, but it seems to be correct to use this pragma.

package main

import (
	"fmt"
	"machine"
	"time"
)

//go:section .constdata
var dummy = []byte("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" +
	"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")

func main() {
	led := machine.LED
	led.Configure(machine.PinConfig{Mode: machine.PinOutput})

	for {
		led.Toggle()
		println("hello world!")
		fmt.Printf("%p %q\r\n", &dummy, string(dummy))
		time.Sleep(time.Second)
	}
}
    .text :
    {
        KEEP(*(.isr_vector))
        *(.text)
        *(.text.*)
        *(.rodata)
        *(.rodata.*)
        *(.constdata)
        *(.constdata.*)
        . = ALIGN(4);
    } >FLASH_TEXT

@sago35
Copy link
Member

sago35 commented Jun 8, 2021

@aykevl
I want a section pragma.
Please resolve conflicts and rebase.

These pragmas weren't really tested anywhere, except that some code
might break if they are not properly applied.

These tests make it easy to see they work correctly and also provide a
logical place to add new pragma tests.

I've also made a slight change to how functions and globals are created:
with the change they're also created in the IR even if they're not
referenced. This makes testing easier.
@aykevl
Copy link
Member Author

aykevl commented Jun 23, 2021

I have rebased the PR to resolve the merge conflict.

With the following code, I was able to place the variable dummy in .text.
There is a PR to put tinyfont data in the const area, but it seems to be correct to use this pragma.

Hmm, this can be a problem. Maybe //go:section should be an unsafe feature for this reason, just like //go:linkname. The problem is that modifying such an array is not possible and there is no way the type system can prevent this.
A better solution might be to store font data as strings: strings can be indexed in the same way as byte arrays but will be stored in flash because they cannot be modified.
An alternative is file embed support, which isn't yet implemented in Go.

@deadprogram
Copy link
Member

Maybe //go:section should be an unsafe feature for this reason, just like //go:linkname

Absolutely yes, this should also require unsafe.

This patch adds a new pragma for functions and globals to set the
section name. This can be useful to place a function or global in a
special device specific section, for example:

  * Functions may be placed in RAM to make them run faster, or in flash
    (if RAM is the default) to not let them take up RAM.
  * DMA memory may only be placed in a special memory area.
  * Some RAM may be faster than other RAM, and some globals may be
    performance critical thus placing them in this special RAM area can
    help.
  * Some (large) global variables may need to be placed in external RAM,
    which can be done by placing them in a special section.

To use it, you have to place a function or global in a special section,
for example:

    //go:section .externalram
    var externalRAMBuffer [1024]byte

This can then be placed in a special section of the linker script, for
example something like this:

    .bss.extram (NOLOAD) : {
        *(.externalram)
    } > ERAM
@aykevl
Copy link
Member Author

aykevl commented Jun 24, 2021

Okay, I've updated it to require an import of unsafe in packages that use //go:section because it allows to do unsafe things.
Just import package unsafe to use it, even if that's import _ "unsafe".

@deadprogram
Copy link
Member

Thanks @aykevl for the revisions. Now merging.

@deadprogram deadprogram merged commit 2bb7081 into dev Jun 24, 2021
@deadprogram deadprogram deleted the section-pragma branch June 24, 2021 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants