Como escrever um bootloader simples para AVR em linguagem C – (Parte 35/46)

Cómo escribir un gestor de arranque simple para AVR en lenguaje C – (Parte 35/46)

BootLoader es un código que se ejecuta cuando se enciende o reinicia un microcontrolador. Básicamente, define un entorno para ejecutar el código de la aplicación. Es el Boot-Loader el que configura el hardware y carga el código de la aplicación desde cualquier medio de almacenamiento o recibido a través de comunicación externa y permite que la aplicación se ejecute. Por tanto, un Boot-Loader debe realizar la siguiente función básica: Inicialice los periféricos del controlador, Inicialice los dispositivos en la placa, Permitir al usuario seleccionar entre las aplicaciones disponibles para cargar, Cargue la aplicación seleccionada, Deje que se ejecute el código de la aplicación. Además de las funciones mencionadas anteriormente, algunos cargadores de arranque pueden realizar muchas otras funciones y hay cargadores de arranque que no realizan todas estas funciones, como brindar la opción de seleccionar la aplicación requerida, etc. Los códigos de cargador de arranque en microcontroladores son en realidad muy pequeños y simples en comparación con los cargadores de arranque en dispositivos avanzados como PC. En la mayoría de los microcontroladores, la funcionalidad de un cargador de arranque se limita a configurar únicamente el reloj inicial y otras configuraciones del microcontrolador, cargar un binario de aplicación desde el puerto serie, etc. En un microcontrolador AVR, escribir un código de cargador de arranque es comparativamente fácil ya que cualquier código escrito en la sección BLS de la memoria flash puede tener acceso completo al hardware del microcontrolador. La memoria flash del microcontrolador AVR se divide en dos secciones; una sección de flash de aplicación y una sección de cargador de arranque (BLS).

Cualquier código ejecutado desde BLS puede utilizar el modo de autoprogramación (SPM). Al utilizar la función SPM, un código de la sección BLS puede leer o escribir toda la memoria flash, incluida la sección BLS desde donde se ejecuta el código. Esta característica se puede utilizar para cargar cualquier código binario de aplicación en la memoria flash y dejarlo ejecutar. Inicialización requerida de los periféricos del controlador como USART, bits de puerto, etc. e inicialización de dispositivos externos como LCD, etc. Se puede hacer desde el propio BLS antes de cargar el código de la aplicación. En este proyecto, analice cómo escribir un código de cargador de arranque más simple para el microcontrolador AVR que pueda inicializar los periféricos como USART, el puerto LED e inicializar una pantalla LCD de 4 bits conectada al controlador y luego cargar cualquier aplicación que se haya actualizado en el Integrado en la EEPROM del microcontrolador. El microcontrolador utilizado en este proyecto es el ATMEGA16 y el programador utilizado es el USBASP. AVR Studio 4 se utiliza como IDE y el software de grabación utilizado es AVR-BURNO-MAT.

La memoria flash del AVR se divide en dos secciones: la sección Aplicaciones y la sección Cargador de arranque (BLS). En el caso de ATMEGA16 dispone de 16 KB de memoria flash de los cuales 15 KB son sección de aplicaciones y el 1 KB restante es BLS. La arquitectura de memoria de ATMEGA16 se muestra en la siguiente figura;

Arquitetura de memória Flash do ATMEGA16

Fig. 2: Arquitectura de memoria flash ATMEGA16

El código para BLS y la sección de aplicación se pueden escribir normalmente y no hay mucha diferencia. Lo único con lo que hay que tener cuidado es con el tamaño del código binario. No debe tener más de 1 KB, de lo contrario no será posible programar código en BLS. El proyecto sobre codificación AVR BLS analiza cómo programar un código simple en el BLS del microcontrolador ATMEGA16 con la ayuda de AVR Studio como IDE, USBasp como programador y AVR-Burnomat como software de grabación.

En este proyecto en particular, el Boot-Loader está codificado para realizar la inicialización UART junto con una simple inicialización del pin LEAD y también una inicialización de hardware externo desde la pantalla LCD de 4 bits . Por lo tanto, los códigos de aplicación no requieren estos códigos, aún funcionan porque antes de ejecutar los códigos de aplicación, el cargador de arranque ejecutará las funciones de inicialización.

El código BLS tiene funciones de inicialización que no deberían estar presentes en los códigos de aplicación. Las funciones de inicialización utilizadas en el código Boot-Loader para este proyecto se detallan a continuación;

Función

Descripción

vacío lcd_init (vacío)

Inicialice la pantalla LCD en modo de 4 bits

usert_init vacío (nulo)

Inicialice el usuario a una velocidad de baudios de 9600 con transmisión y recepción habilitadas

DDRD = 0x80;

Inicialización del pin LED como salida

Fig.3: Funciones de arranque utilizadas Código del cargador de arranque AVR

Cualquier código de aplicación puede usar directamente las siguientes llamadas a funciones para acceder a USART, LCD y LED sin inicializar sus funciones en ninguna parte del código.

Función

Descripción

lcd_claro

Limpiar la pantalla LCD

cadena_lcd

Mostrar una cadena en la pantalla LCD

cadena_envío_usuario

Enviar una cadena a través de usuario

PUERTO &= 0x7F;

Enciende el LED

PUERTO = 0x80;

Apague el LED

Fig. 4: Llamadas a funciones utilizadas por el código de la aplicación para acceder a los periféricos del AVR

La inicialización del hardware antes de ejecutar el código de la aplicación se explica en detalle en un proyecto. en Inicialización del hardware AVR BLS.

La función principal del Boot-Loader es cargar código en formato binario desde un medio de almacenamiento o que pueda recibirse a través de comunicación externa con otros dispositivos a la memoria flash. El recurso SPM disponible para el código que se ejecuta en BLS ayuda a cargar el código binario de la aplicación en la memoria flash. La tarea de escribir código BLS con SPM se ha simplificado gracias a las API disponibles en el archivo de encabezado. . A continuación se muestran las API importantes disponibles en el archivo de encabezado que ayudan en SPM.

FUNCIÓN

DESCRIPCIÓN

PARÁMETRO

boot_page_erase (dirección)

Eliminar la página flash a la que hace referencia la dirección

Una dirección de byte en flash

boot_page_fill (dirección, datos)

Llene el búfer de página temporal de Boot-Loader para la dirección flash con palabra de datos

La dirección es una dirección de bytes. Los datos son una palabra.

boot_page_write (dirección)

Escriba el búfer de la página temporal del Boot-Loader en la página flash que contiene la dirección

Dirección de bytes flash

Figura 5: API importantes en AVR

Los pasos necesarios para realizar SPM en la memoria flash de la aplicación se explican en un proyecto sobre el uso de SPM en la programación flash a flash de AVR.

En este proyecto en particular, el Boot-Loader está codificado de tal manera que intentará cargar cualquier código binario de aplicación que haya sido cargado en la EEPROM interna incorporada del microcontrolador AVR. Las API disponibles en se utilizan para leer los bytes de datos de la EEPROM y con la ayuda del los bytes de datos se almacenan en un búfer temporal y luego se transfieren a la sección de aplicación de la memoria flash.

La API proporcionada por leer los bytes de datos de la EEPROM integrada del microcontrolador AVR;

uint8_t eeprom_read_byte (const uint8_t *p)

FUNCIÓN

DESCRIPCIÓN

PARÁMETRO

uint8_t eeprom_read_byte (const uint8_t *p)

La función devuelve un byte de datos que se almacena en la dirección EEPROM a la que hace referencia el puntero p

El puntero se refiere a la dirección EEPROM desde la cual se debe leer el byte de datos.

Figura 6: API para leer bytes de datos de la EEPROM integrada del microcontrolador AVR

Con la ayuda de las API analizadas anteriormente Es Se puede utilizar la función SPM del microcontrolador AVR para escribir un código de cargador de arranque que pueda cargar una aplicación que haya sido programada en la EEPROM incorporada del microcontrolador AVR. Para ello deberás seguir los pasos que se mencionan a continuación, los cuales se explican en un proyecto sobre el uso de SPM en AVR EEPROM para programación flash.

{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} · {C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} Paso: 1 Elimine la página flash que está a punto de escribir

{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} · {C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} Paso: 2 Almacene el código binario que se lee desde EEPROM en un búfer temporal antes de escribir en una página flash

{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} · {C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C}{C} Paso: 3 Programar el búfer temporal lleno en la página flash ya eliminada

Después de realizar los tres pasos anteriores, el cargador de arranque puede saltar usando la instrucción

asm(“jmp 0x0000”);

a la sección del código de la aplicación y deje que se ejecute la aplicación recién programada.

Primero actualice el código del cargador de arranque al BLS y cualquier código de aplicación de tamaño pequeño a la memoria EEPROM siguiendo los pasos explicados en el proyecto anterior sobre el LED parpadeante del AVR BLS . Una vez que se completa la programación de EEPROM y se reinicia el controlador, el cargador de arranque comenzará a ejecutarse. Se puede ver que está realizando funciones de inicialización y cargando la aplicación desde la EEPROM integrada.

Gravando código BLS no BLS do circuito AVR na placa de ensaio

Fig. 7: Escribir código BLS en el BLS del circuito AVR en la placa de pruebas

Como escrever um bootloader simples para AVR em linguagem C

Display LCD inicializado pelo código BLS na configuração do AVR na placa de ensaio

Fig. 9: Pantalla LCD inicializada por código BLS en configuración AVR en placa

Como escrever um bootloader simples para AVR em linguagem C

Fig. 10: USART inicializado con velocidad de baudios 9600 mediante BLS de configuración AVR en la placa

Como escrever um bootloader simples para AVR em linguagem C

Código fuente del proyecto

###


 #definir F_CPU 8000000
#incluir #incluir #incluir #incluir #incluir #incluir #incluir #incluir #incluir "usart.h" #incluir "lcd.h" int principal (nulo) { uint16_ti; uint8_tA(512); registro uint8_t; página uint32_t = 0; uint16_tw; carácter sin firmar *buf = A; volátil int j = 4; //================================================== ========= == ===================================== lcd_init; //inicialización LCD lcd_claro; lcd_1st_line; lcd_string("INGENIEROS"); lcd_2nd_line; lcd_string("GARAJE"); _delay_ms(3000); lcd_claro; lcd_1st_line; lcd_string("Inicializando ATMEGA16"); _delay_ms(2000); lcd_claro; lcd_1st_line; lcd_string("LCD(OK)"); lcd_2nd_line; lcd_string("16*2,4 bits"); _delay_ms(2000); usuariot_init; //inicialización USART lcd_claro; lcd_1st_line; lcd_string("USART(OK)"); lcd_2nd_line; lcd_string("9600bps, Tx y Rx"); _delay_ms(2000); lcd_claro; lcd_1st_line; lcd_string("cargando aplicación... "); lcd_2nd_line; para(yo = 0; yo < 16; yo++) { _delay_ms(350); datos_dis(0xFF); } lcd_claro; lcd_1st_line; //================================================== ========= == ===================================== //############################### Arranque desde EEPROM ############## # # ################// para (yo = 0; yo < 512; yo++) A (i) = eeprom_read_byte ((const uint8_t *) i); mientras(1) { //================================================== ========= == =========================// si(j) { //Desactiva las interrupciones. reg = SREG; cli; eeprom_busy_wait; boot_page_erase (página); boot_spm_busy_wait; //Espera hasta que se borre la memoria. para (i=0; yo { //Configura la palabra little-endian. w = *buf++; w += (*buf++) << 8; boot_page_fill(página + i, w); } boot_page_write (página); // Almacenar el búfer en la página flash. boot_spm_busy_wait; //Espera hasta que se escriba la memoria. boot_rww_enable; SREG = sreg; } otro { asm("jmp 0x0000"); } j--; página = página + 128; //================================================== ========= == ========================================= ====// } //############################### Arranque desde EEPROM ############## # # ################// } //#################### LCD ########################//

#definir _LCD_H #ifndef F_CPU #definir F_CPU 8000000 #endif #incluir #incluir #incluir #define rs PA0 #define rw PA1 #define en PA2 void lcd_init; vacío dis_cmd(char); vacío dis_data(char); vacío lcdcmd(char); void lcddata(char); vacío lcd_clear(vacío); vacío lcd_2nd_line (vacío); vacío lcd_1st_line (vacío); void lcd_string(const char *datos); void lcd_string(const char *datos) { for(;*datos;datos++) dis_data (*datos); } void lcd_clear(void) { dis_cmd(0x01); _delay_ms(10); } void lcd_2nd_line(void) { dis_cmd(0xC0); _delay_ms(1); } void lcd_1st_line(void) { dis_cmd(0x80); _delay_ms(1); } void lcd_init // función para inicializar { DDRA=0xFF; dis_cmd(0x02); // para inicializar la pantalla LCD en modo de 4 bits. dis_cmd(0x28); //para inicializar la pantalla LCD en 2 líneas, 5X7 puntos y modo de 4 bits. dis_cmd(0x0C); dis_cmd(0x06); dis_cmd(0x80); dis_cmd(0x01); _delay_ms(10); } void dis_cmd(char cmd_value) { char cmd_value1; cmd_valor1 = cmd_valor & 0xF0; //enmascara el mordisco inferior porque se utilizan los pines PA4-PA7. lcdcmd(cmd_valor1); // enviar a la pantalla LCD cmd_value1 = ((cmd_value<<4) & 0xF0); //cambia 4 bits y enmascara lcdcmd(cmd_value1); //enviar a LCD } void dis_data(char data_value) { char data_value1; valor_datos1=valor_datos&0xF0; lcddata(valor_datos1); valor_datos1=((valor_datos<<4)&0xF0); lcddata(valor_datos1); } void lcdcmd(char cmdout) { PORTA=cmdout; PUERTA&=~(1<

###

Código fuente del proyecto

###


 #ifndef _USART_H
#definir _USART_H #ifndef F_CPU #definir F_CPU 8000000 #terminara si #definir USART_BAUDRATE 9600 #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) #incluir #incluir anular usert_init; void usert_putch (envío de caracteres sin firmar); sin firmar int user_getch; anular user_init { UCSRB = (1 << RXEN) (1 << TXEN); //Activa el circuito de transmisión y recepción. UCSRC = (1 << URSEL) (1< //Utiliza tamaños de caracteres de 8 bits UBRRL = BAUD_PRESCALE; // Carga los 8 bits inferiores del valor de velocidad en baudios. //en el byte bajo del registro UBRR UBRRH = (BAUD_PRESCALE >> 8); // Carga los 8 bits superiores del valor de velocidad en baudios. //en el byte alto del registro UBRR } void usert_putch (envío de caracteres sin firmar) { mientras ((UCSRA & (1 << UDRE)) == 0); // No hacer nada hasta que la UDR esté lista. // para que se escriban más datos en él UDR = enviar; // envía el byte } int sin firmar use_getch { mientras ((UCSRA & (1 << RXC)) == 0); // No hacer nada hasta que los datos se hayan recibido y estén listos para ser leídos en la UDR retorno(UDR); //devuelve el byte } #terminara si

#definir rs PA0 #definir rw PA1 #definir en PA2 #incluir #incluir void dis_data(char datos_valor); void usert_putch (envío de caracteres sin firmar); sin firmar int user_getch; int principal(vacío) { int i; int sin firmar c; //-------- prueba de LED -----------// DDRD = 0x80; for (i =0; i < 5; i++) { PORTD = ~PORTD; _delay_ms(500); } //-------- prueba de led -----------// //----- usuario + prueba de lcd -------// while ( 1 ) {c = usuario_getch; usert_putch((carácter sin firmar)c); dis_data((char)c); } //----- usar + prueba LCD -------// } void dis_data(char data_value) { char data_value1; valor_datos1=valor_datos&0xF0; PUERTO=valor_datos1; PUERTO =(1<


###

Diagramas de circuito

Diagrama de circuito de cómo escribir un gestor de arranque simple para AVR en lenguaje C

Componentes del proyecto

  • ATmega16
  • LCD
  • CONDUJO
  • Resistor

Vídeo del proyecto

Conteúdo Relacionado

En cada vehículo hay una red de sensores integrada...
El controlador del motor es uno de los componentes...
ESP32-CAM es un módulo de cámara compacto que combina...
La evolución de los estándares USB ha sido fundamental...
SCHURTER anuncia una mejora de su popular serie SWZ...
Visual Communications Company (VCC) ha anunciado sus nuevos tubos...
A Sealevel Systems anuncia o lançamento da Interface Serial...
A STMicroelectronics introduziu Diodos retificadores Schottky de trincheira de...
Determinar uma localização precisa é necessário em várias indústrias...
O novo VIPerGaN50 da STMicroelectronics simplifica a construção de...
A Samsung Electronics, fornecedora de tecnologia de memória avançada,...
O mercado embarcado tem uma necessidade de soluções de...
Probablemente se haya encontrado con el término " resistencia...
Probablemente tenga un aislante de soporte si ha notado...
Probablemente haya visto un aislante colocado en postes de...
Probablemente hayas visto aisladores de grillete entronizados en postes...
Probablemente hayas experimentado situaciones en las que controlar un...
Regresar al blog

Deja un comentario

Ten en cuenta que los comentarios deben aprobarse antes de que se publiquen.