SISTEMAS EMBEBIDOS
Unidad 1.2 – Desarrollo de software embebido
Photo by Tim Simpson
Herramientas de desarrollo
Conceptos (repaso):
Tool chain
Herramientas (compilador, ensamblador, etc.) compatibles
Herramientas nativas (native tools)
Crea programas que corren en la computadora que se compila
Host (donde se desarrolla) vs. target (destino)
“Compilador cruzado” (cross-compiler)
Compilador en host produce instrucciones binarias target
Instituto San Antonio de Padua
Sistemas embebidos Página 2
Proceso de creación y cargado:
programa de aplicación de escritorio
Loader
Object Files
Compiler
Compiler Executable
Image File
Read-Write
L L Memory (RAM)
in o
Linker
Assembler
Assembler k a
er d
er
Run-Time Library:
Boot
Boot
Operating System Image: Process
Proces
s
Fuente: Daniel W. Lewis, “Fundamentals of Embedded Software”
Instituto San Antonio de Padua
Sistemas embebidos Página 3
Compilador
Traduce código fuente en lenguaje C a instrucciones de máquina
generando un archivo objeto
main.c main.obj
int aux1,aux2; …
… MOVE R1,(aux1)
aux2 = Compilador CALL fun1
fun1(aux1); …
…
Instituto San Antonio de Padua
Sistemas embebidos Página 4
Enlazador (Linker)
El linker “junta” todos los archivos, resolviendo las referencias
entres los archivos
Determina las direcciones de las etiquetas que el compilador no pudo
resolver
Por ejemplo: funciones y variables externas (extern) definidas en
otros archivos
prog..exe
main.obj
…
…
MOVE R1,2388
MOVE R1,(aux1)
CALL 1547
CALL fun1 …
… auxiliares.obj Linker …
… …
fun1: 1547 [inicio fun1]
… …
2388 [valor de aux]
…
Instituto San Antonio de Padua
Sistemas embebidos Página 5
Loader
El loader debe ajustar las direcciones de memoria absolutas del
código y de los datos en función de la dirección de base
Obs.: cada vez pude ser cargado en diferentes regiones de memoria
prog..exe
…
MOVE R1,2388
CALL 1547
…
… Memoria
Loader
…
1547 MOVE R1, R5
… 21547
2388 [valor de aux]
… 22388
Instituto San Antonio de Padua
Sistemas embebidos Página 6
Loader
No necesitan ajustes:
Las direcciones relativas al PC en sistemas con memoria virtual
prog..exe
…
MOVE R1,2388
CALL 1547
…
… Memoria
Loader
…
1547 MOVE R1, R5
… 21547
2388 [valor de aux]
… 22388
Instituto San Antonio de Padua
Sistemas embebidos Página 7
Proceso de creación y cargado:
programa de aplicación embebido
Object Files
Read-Write
Memory
Read-Write
Cross-
Cross- (RAM)
Memory
Compiler
Compiler Executable ROM
(RAM)
Image File Image File
Locator
Cross-
Cross- L
Assembler
Assembler o
c
Linker
a
tr o
Re-Entrant Library:
L Read-Only
in Memory
Read-Only
k ROM (ROM)
er Memory
Real-Time Kernel: ROM
"Burner" (ROM)
"Burner"
tos básicos Sistemas embebidos de tiempo
Fuente: real“Fundamentals of Embedded Software”
Daniel W. Lewis,
Instituto San Antonio de Padua
Sistemas embebidos Página 8
(No) Portabilidad de binarios
Intrínseco de la compilación a código máquina (directam. exec.):
Compiladores nativos y compiladores-cruzados
Ejemplo de compilador nativo:
Pensar que un programa en C compila con en una plataforma (HW,
SO)...
¿Qué problemas se tienen al cambiar de plataforma?
Ejemplo de compiladores-cruzados:
Pensar que se compila para un microcontrolador dado...
¿Qué problemas se tienen al cambiar de microcontrolador?
Instituto San Antonio de Padua
Sistemas embebidos Página 9
Locator
Funcionalidad muy distinta a la del loader
Determina la imagen final en memoria del programa
No existe un proceso similar al correspondiente del loader
Es posible crear la imagen final porque:
Es el único programa en memoria, no existen conflictos por recursos
Es posible determinar la dirección final de todo, incluyendo el kernel (si lo
hubiera) y las funciones de biblioteca
Es posible indicar la ubicación en memoria
Datos, código
RAM, ROM
Instituto San Antonio de Padua
Sistemas embebidos Página 10
Ubicación en memoria
Tener en cuenta:
Datos persistentes necesitan estar en NVM (non-volatile memory)
Datos modificables necesitan estar en RAM
¿Como sabe el linker/locator dónde poner cada cosa?
El programa se organiza en segmentos que son tratados independientemente
Segmentos
Compilador: crea entidades lógicas conteniendo código o datos
Linker: agrupa segmentos de diferentes códigos objeto
Locator: mapea los segmentos en una ubicación física de memoria
Ejemplo de categorías:
CODE
XDATA
Instituto San Antonio de Padua
Sistemas embebidos Página 11
Inicialización de datos
Requerimientos:
Valor inicial (persistente entre reset) → ROM o Flash
Variable (modificable en ejecución) → RAM
Problema:
Valor inicial debe ser copiado en el arranque
Solución:
¿Cómo?
Copiar segmentos “shadow” (con los valores iniciales) de ROM a RAM (más
adelante ejemplo)
¿Quién?
Startup code (código de arranque) ejecutado antes del “main”
Instituto San Antonio de Padua
Sistemas embebidos Página 12
Inicialización de datos (2)
El estándar C especifica:
Variables estáticas (non-stack) no inicializadas se inicializan en cero
Requerimientos:
Variable (modificable en ejecución) → RAM
Valor inicial → cero
Solución:
Se realiza un memset (a cero)
Startup code incluye esa rutina
Instituto San Antonio de Padua
Sistemas embebidos Página 13
Ejemplo
x.c y.c z.asm Módulos:
x.c
cross- cross- cross-
compiler compiler assembler Instrucciones
x.obj y.obj z.obj Datos sin inicializar
Constantes strings
y.c
Instrucciones
Datos inicializados y sin
inicializar
z.asm
Funciones en asm
Datos sin inicializar
“Startup-code”
Instituto San Antonio de Padua
Sistemas embebidos Página 14
Ejemplo
x.c y.c z.asm
Cross-compiler
cross- cross- cross-
Divide archivo fuente en
compiler compiler assembler segmentos
x.obj y.obj y.c z.obj
x.c
code code
z.asm
code Directivas al cross-comp
x.c y.c z.asm
udata udata udata #pragma
x.c y.c z.asm
string idata start
Segmentos:
code: instrucciones
udata: datos sin inicializar
idata: datos inicializados
string: constantes strings
Instituto San Antonio de Padua
Sistemas embebidos Página 15
Ejemplo
x.c y.c z.asm
Segmentos
cross- cross- cross-
code: instrucciones
compiler compiler assembler
x.obj y.obj y.c z.obj
udata: datos sin inicializar
x.c z.asm
idata: datos inicializados
code code code
x.c y.c z.asm
udata udata udata
x.c y.c z.asm
string: constantes strings
string idata start
linker/locator
Linker/locator
ROM
z.asm
start
“Compagina” segmentos
x.c x.c
code RAM udata
y.c
“start-code” copia
idatshadow a idata en el
y.c
code udata
arranque
z.asm z.asm
code udata
x.c y.c
idatshadw es copiado a idata idata
string
en el arranque
y.c
idatshadw
Instituto San Antonio de Padua
Sistemas embebidos Página 16
Locator maps ****************************************
*
*
*
CROSS REFERENCE
*
*
*
****************************************
Program entry at : 020A Relocatable, from module : ?cstart
****************************************
Mapa:
* *
*
*
MODULE MAP
****************************************
*
*
DEFINED ABSOLUTE ENTRIES
Salida adicional del
*****************************************************************
DEFINED ABSOLUTE ENTRIES
PROGRAM MODULE, NAME : ?ABS_ENTRY_MOD
locator Absolute parts
ENTRY ADDRESS REF BY
===== ======= ======
_HEAP_SIZE 0050
Usualmente *.map
_STACK_SIZE 0050
*****************************************************************
FILE NAME : C:\temp\Debug\Obj\segment.r43
PROGRAM MODULE, NAME : segment
SEGMENTS IN THE MODULE
Resumen: ======================
DATA16_C
Relative segment, address: 025C - 0265 (0xa bytes), align: 0
Segment part 2. Intra module refs: str1
-----------------------------------------------------------------
DATA16_C
Ubicación del código,
Relative segment, address: 025A - 025B (0x2 bytes), align: 1
Segment part 3. Intra module refs: main
ENTRY ADDRESS REF BY
===== ======= ======
variables, etc. en los str1 025A
-----------------------------------------------------------------
DATA16_Z
Relative segment, address: 0200 - 0209 (0xa bytes), align: 0
diferentes segmentos Segment part 4. Intra module refs: main
ENTRY ADDRESS REF BY
===== ======= ======
str2 0200
-----------------------------------------------------------------
CODE
Relative segment, address: 0222 - 023D (0x1c bytes), align: 1
Segment part 5.
ENTRY ADDRESS REF BY
===== ======= ======
main 0222 Segment part 12
stack 1 = 00000000 ( 00000002 )
*****************************************************************
Instituto San Antonio de Padua
Sistemas embebidos Página 17
Ejemplo: compilador IAR C/C++
Tipos de segmentos
CODE: código ejecutable
CONST: datos ubicados en ROM
DATA: datos ubicados en RAM
Nomenclatura: nombrebase_sufijo
Nombre base
Por ejemplo: DATA16 (MSP430), NEAR (AVR)
Sufijo (categoría):
Datos no inicializados: N
Datos inicializados a cero: Z
Datos inicializados non-cero: I
Inicializadores para el anterior: ID
Constantes: C
Etc.
Instituto San Antonio de Padua
Sistemas embebidos Página 18
Ejemplos
ejemplo.c
...
...
int i = 0;
Variables que son inicializadas a
int j = 4;
cero son ubicadas en el
... segmento DATA16_Z
...
Variables inicializadas a valores
distintos de cero son ubicadas en
el segmento DATA16_I y un
segmento de inicialización en
DATA16_ID.
Instituto San Antonio de Padua
Sistemas embebidos Página 19
Compilador IAR C/C++
Segmento CSTART
contiene código para:
Arranque (cstartup)
Terminación (exit)
main() {
}//end main
Instituto San Antonio de Padua
Sistemas embebidos Página 20
Otros temas sobre inicialización
Constantes strings: char *sMsg = “Alarma”;
¿Dónde se guarda esta constante?
¿Qué pasa si modificamos este string?
Es válido en C
Cross-compilers resuelven este problema de diferentes maneras.
En función si es declarado constante: char* const ..
Si es modificado o no en el código
Instituto San Antonio de Padua
Sistemas embebidos Página 21
Ejemplo SEGMENTS IN THE MODULE
======================
DATA16_I
Relative segment, address: 0200 - 0201 (0x2 bytes), align: 1
Segment part 3. Intra module refs: main
ENTRY ADDRESS REF BY
ej-string.c 0200
str1
-----------------------------------------------------------
char* str1 = "Hola chau"; DATA16_Z
char str2[10]; Relative segment, address: 0202 - 020B (0xa bytes), align: 0
Segment part 5. Intra module refs: main
int main( void ) ENTRY ADDRESS REF BY
{ str2 0202
char* c1; -----------------------------------------------------------
char* c2; c1=str1; CODE
c2=str2; Relative segment, address: 0236 - 0251 (0x1c bytes), align: 1
for(;*c1!=0;c1++,c2++) Segment part 6.
*c2 = *c1; ENTRY ADDRES REF BY
} main S 0236 Seg. part 12 (?cstart)
stack 1 = 00000000 ( 00000002 )
-----------------------------------------------------------
DATA16_ID
Relative segment, address: 02A0 - 02A1 (0x2 bytes), align: 1
Segment part 4. Intra module refs: str1
-----------------------------------------------------------
DATA16_C
Relative segment, address: 0296 - 029F (0xa bytes), align: 0
Segment part 2. Intra module refs: Seg. part 4
Instituto San Antonio de Padua
Sistemas embebidos Página 22
Ejemplo SEGMENTS IN THE MODULE
======================
DATA16_C
Relative segment, address: 025C - 0265 (0xa bytes), align: 0
Segment part 2. Intra module refs: str1
-----------------------------------------------------------
ej-string.c DATA16_C
Relative segment, address: 025A - 025B (0x2 bytes), align: 1
char* const str1 = "Hola chau"; Segment part 3. Intra module refs: main
char str2[10]; ENTRY ADDRESS REF BY
str1 025A
int main( void ) -----------------------------------------------------------
{ DATA16_Z
char* c1; Relative segment, address: 0200 - 0209 (0xa bytes), align: 0
char* c2; c1=str1; Segment part 4. Intra module refs: main
c2=str2; ENTRY ADDRESS REF BY
for(;*c1!=0;c1++,c2++) str2 0200
*c2 = *c1; -----------------------------------------------------------
} CODE
Relative segment, address: 0222 - 023D (0x1c bytes), align: 1
Segment part 5.
ENTRY ADDRESS REF BY
main 0222 Seg. part 12 (?cstart)
stack 1 = 00000000 ( 00000002 )
Instituto San Antonio de Padua
Sistemas embebidos Página 23
Cargado del programa en destino
Alternativas:
Grabarlo en ROM o PROM, y después insertar el chip en la placa
Usar un Emulador ROM
Escribirlo en la memoria flash destino
Usar un “in-circuit emulator”
Instituto San Antonio de Padua
Sistemas embebidos Página 24
Memoria Flash
Flash programable en campo
Host se conecta al target y reprograma la Flash directamente sin
necesidad de cambiar chips
Cargado del programa
BSL (bootstrap loader) copia el programa en flash
JTAG
Instituto San Antonio de Padua
Sistemas embebidos Página 25
In-circuit emulator (programming)
(Atención: paradójicamente ya no es emulado...)
Toma el lugar del microprocesador en el sistema
Para el resto del hardware es un micro común
Programable o controlado por el host
Funcionalidad similar a un debugger de escritorio
Set breakpoints
Single-step
Volcado de registros y memoria
Ejemplo:
Flash Emulation Tool (FET): prototipado y desarrollo
Interfaz JTAG
Instituto San Antonio de Padua
Sistemas embebidos Página 26
Actualizaciones en campo
Corregir código en producto es caro
Debe llevar el producto para actualizar el programa (memoria) o
incluso el cliente podría hacerlo
Algunos productos permiten actualización automática
Receptores de TV Satélite
Teléfonos celulares
Motes: “on the fly”
No es fácil:
Si la imagen obtenida está corrupta (problemas de comunicación),
después no anda...
Instituto San Antonio de Padua
Sistemas embebidos Página 27
¿Por qué segmentos?
Cada segmento puede ser ubicado separadamente en el lugar
deseado de memoria física
Ejemplos:
Segmentos de código pude ser ubicado en ROM
Segmentos de datos constantes pueden ser ubicados en ROM
Segmentos de datos modificables pueden ser ubicados en RAM
Segmento especial “Start Code” es ubicado automáticamente para
que sea lo primero que se ejecute después de un reset
Instituto San Antonio de Padua
Sistemas embebidos Página 28
Creación de segmentos
Creados automáticamente por el compilador
Se realiza también para programas de escritorio, pero normalmente
es transparente para el usuario
En lenguaje ensamblador el programador debe hacerlos
explícitamente
Los ensambladores no son suficientemente sofisticados para
manejarlos de manera transparente (DSP: ¿se acuerdan?)
Los nombres deben ser consistentes con la convención del
compilador
Todos los sistemas tienen categorías similares de segmentos
Pero el nombre depende de las herramientas en particular
Por ejemplo: CODE, XDATA, o DATA, etc.
Instituto San Antonio de Padua
Sistemas embebidos Página 29
Ejecución desde RAM
RAM en general mas rápida que Flash y ROM
Código de arranque (startup code) debe copiar el programa de
ROM a RAM, y después transferirle el control
Considerar el nuevo desafío para el locator:
Crear un programa que es guardado a partir de cierta dirección (en
ROM), pero debe correr correctamente en otra dirección (en RAM)
No es tan fácil: RTOS a veces vienen con herramientas que lo realiza
Instituto San Antonio de Padua
Sistemas embebidos Página 30
Debate
Misceláneas de programación
Guía de estilo
Técnicas de programación
XP
Programación de a pares (pair programming)
Otros
Instituto San Antonio de Padua
Sistemas embebidos Página 31
¡Muchas gracias por su atención!
Instituto San Antonio de Padua
Sistemas embebidos Página 32