docs: add page "Go on microcontrollers"
Этот коммит содержится в:
		
							родитель
							
								
									823ecd5167
								
							
						
					
					
						коммит
						0e65b0da1c
					
				
					 2 изменённых файлов: 133 добавлений и 0 удалений
				
			
		| 
						 | 
				
			
			@ -12,4 +12,5 @@ Contents:
 | 
			
		|||
   :maxdepth: 2
 | 
			
		||||
 | 
			
		||||
   installation
 | 
			
		||||
   microcontrollers
 | 
			
		||||
   internals
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										132
									
								
								docs/microcontrollers.rst
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										132
									
								
								docs/microcontrollers.rst
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
				
			
			@ -0,0 +1,132 @@
 | 
			
		|||
.. microcontrollers:
 | 
			
		||||
 | 
			
		||||
.. highlight:: go
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Go on microcontrollers
 | 
			
		||||
======================
 | 
			
		||||
 | 
			
		||||
TinyGo was designed to run on microcontrollers, but the Go language wasn't.
 | 
			
		||||
This means there are a few challenges to writing Go code for microcontrollers.
 | 
			
		||||
 | 
			
		||||
Microcontrollers have very little RAM and execute code directly from flash.
 | 
			
		||||
Also, constant globals are generally put in flash whenever possible. The Go
 | 
			
		||||
language itself heavily relies on garbage collection so care must be taken to
 | 
			
		||||
avoid dynamic memory allocation.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Heap allocation
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
Many operations in Go rely on heap allocation. Some of these heap allocations
 | 
			
		||||
are optimized away, but not all of them. Also, TinyGo does not yet contain a
 | 
			
		||||
garbage collector so heap allocation must be avoided whenever possible outside
 | 
			
		||||
of initialization code.
 | 
			
		||||
 | 
			
		||||
These operations currently do heap allocations:
 | 
			
		||||
 | 
			
		||||
  * Taking the pointer of a local variable. This will result in a heap
 | 
			
		||||
    allocation, unless the compiler can see the resulting pointer never
 | 
			
		||||
    escapes. This causes a heap allocation::
 | 
			
		||||
 | 
			
		||||
        var global *int
 | 
			
		||||
 | 
			
		||||
        func foo() {
 | 
			
		||||
            i := 3
 | 
			
		||||
            global = &i
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    This does not cause a heap allocation::
 | 
			
		||||
 | 
			
		||||
        func foo() {
 | 
			
		||||
            i := 3
 | 
			
		||||
            bar(&i)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        func bar(i *int) {
 | 
			
		||||
            println(*i)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  * Converting between ``string`` and ``[]byte``. In general, this causes a
 | 
			
		||||
    heap allocation because one is constant while the other is not: for
 | 
			
		||||
    example, a ``[]byte`` is not allowed to write to the underlying buffer of a
 | 
			
		||||
    ``string``. However, there is an optimization that avoids a heap allocation
 | 
			
		||||
    when converting a string to a ``[]byte`` when the compiler can see the
 | 
			
		||||
    slice is never written to. For example, this ``WriteString`` function does
 | 
			
		||||
    not cause a heap allocation::
 | 
			
		||||
 | 
			
		||||
        func WriteString(s string) {
 | 
			
		||||
            Write([]byte(s))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        func Write(buf []byte) {
 | 
			
		||||
            for _, c := range buf {
 | 
			
		||||
                WriteByte(c)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  * Converting a ``byte`` or ``rune`` into a ``string``. This operation is
 | 
			
		||||
    actually a conversion from a Unicode code point into a single-character
 | 
			
		||||
    string so is similar to the previous point.
 | 
			
		||||
 | 
			
		||||
  * Concatenating strings, unless one of them is zero length.
 | 
			
		||||
 | 
			
		||||
  * Creating an interface with a value larger than a pointer. Interfaces in Go
 | 
			
		||||
    are not a zero-cost abstraction and should be used carefully on
 | 
			
		||||
    microcontrollers.
 | 
			
		||||
 | 
			
		||||
  * Closures where the collection of shared variables between the closure and
 | 
			
		||||
    the main function is larger than a pointer.
 | 
			
		||||
 | 
			
		||||
  * Creating and modifying maps. Maps have *very* little support at the moment
 | 
			
		||||
    and should not yet be used. They exist mostly for compatibility with some
 | 
			
		||||
    standard library packages.
 | 
			
		||||
 | 
			
		||||
  * Starting goroutines. There is limited support for goroutines and currently
 | 
			
		||||
    they are not at all efficient. Also, there is no support for channels yet
 | 
			
		||||
    so their usefulness is limited.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The ``volatile`` keyword
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
Go does not have the ``volatile`` keyword like C/C++. This keyword is
 | 
			
		||||
unnecessary in most desktop use cases but is required for memory mapped I/O on
 | 
			
		||||
microcontrollers and interrupt handlers. As a workaround, any variable of a
 | 
			
		||||
type annotated with the ``//go:volatile`` pragma will be marked volatile. For
 | 
			
		||||
example::
 | 
			
		||||
 | 
			
		||||
    //go:volatile
 | 
			
		||||
    type volatileBool bool
 | 
			
		||||
 | 
			
		||||
    var isrFlag volatileBool
 | 
			
		||||
 | 
			
		||||
This is a workaround for a limitation in the Go language and should at some
 | 
			
		||||
point be replaced with something else.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Inline assembly
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
The device-specific packages like ``device/avr`` and ``device/arm`` provide
 | 
			
		||||
``Asm`` functions which you can use to write inline assembly::
 | 
			
		||||
 | 
			
		||||
    arm.Asm("wfi")
 | 
			
		||||
 | 
			
		||||
There is no support yet for inline assembly that takes (register) parameters or
 | 
			
		||||
returns a value.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Harvard architectures (AVR)
 | 
			
		||||
---------------------------
 | 
			
		||||
 | 
			
		||||
The AVR architecture is a modified Harvard architecture, which means that flash
 | 
			
		||||
and RAM live in different address spaces. In practice, this means that any
 | 
			
		||||
given pointer may either point to RAM or flash, but this is not visible from
 | 
			
		||||
the pointer itself.
 | 
			
		||||
 | 
			
		||||
To get TinyGo to work on the Arduino, which uses the AVR architecutre, all
 | 
			
		||||
global variables (which include string constants!) are marked non-constant and
 | 
			
		||||
thus are stored in RAM and all pointer dereferences assume that pointers point
 | 
			
		||||
to RAM. At some point this should be optimized so that obviously constant data
 | 
			
		||||
is kept in read-only memory but this optimization has not yet been implemented.
 | 
			
		||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче