sábado, 5 de marzo de 2022

Proteccion de la memoria ATmega

Como impedir que copien nuestro Arduino


Les doy la bienvenida a esta entrada en la quiero responder a la pregunta que me han hecho en varias oportunidades, "¿Como hacer para que no copien mi proyecto realizado en Arduino?". Pues bien, ante la consulta debo recordar que el principio de utilizar una plataforma de código abierto como Arduino, implica que el proyecto(software) elaborado no debería tener propietarios, mas al contrario compartir tu trabajo representa un pilar fundamental en el desarrollo de la plataforma. Ahora si pese a esto tu no quieres que alguien copie tu proyecto porque representa una idea original con muchas noches en desvelo, en esta entrada te explicare como hacerlo.
 

Para empezar listare las cosas que necesitaremos:

  • Un programador(UsbASP, UTK500, ArduinoISP, etc);
  • Una tarjeta Arduino(UNO, Mega o Nano);
  • Software de programación para AVR(avrdude, avrp, uisp, etc).

Utilizaremos el programador UsbASP por ser una de las opciones mas asequibles, junto al software de programación avrdude y la tarjeta Arduino UNO.

Fig1. Programador UsbASP


Este programador nos posibilita leer y cargar el código del microcontrolador en la memoria de programa FLASH y EEPROM utilizando el modo SPI, conectando de forma fácil y practica al puerto ISP de la tarjeta Arduino UNO. Otra alternativa interesante es cargar en una tarjeta Arduino el código <ArduinoISP> y utilizarlo como programador para otras tarjetas, eso si necesitara efectuar las respectivas conexiones puente entre ambos.

La forma de como llevar a cabo la protección de la tarjeta Arduino UNO, es programando los bits del registro LOCK que restringe el acceso a la memoria del microcontrolador, en particular los bits LB2 y LB1

Fig2. bits del registro LOCK

Por defecto los bits del registro LOCK están sin programar o desactivados, lo que representa un valor 0xFF, estos bits pueden ser activados con valor 0 en cualquier instante, pero una vez programados, la única forma de restablecer su valor es borrando toda la memoria de microcontrolador con la instrucción chip erase.

avrdude es un programa simple de linea de comandos disponible para linux y windows, que nos permitirá llevar a cabo la carga y descarga del código que contiene la memoria de programa y datos del microcontrolador Atmega, además de configurar los fusibles y el registro LOCK. 

El conjunto de instrucciones de avrdude es bastante amplio por esa razón solo nos centraremos en aplicar el comando con los parámetros mínimos necesarios para llevar a cabo la protección.

La instalación de avrdude en el caso Linux/Debian solo requiere la ejecución del siguiente comando desde una terminal de consola:

#apt-get install avrdude 

También dejo algunos enlaces de ayuda en caso de utilizar Windows:


Ahora describiré el proceso para efectuar la protección en tres pasos.

PASO 1 (Cargar el código a la memoria de programa)

Se entiende por código al fichero hex o firmare generado por el compilador, y no así al código fuente elaborado por el desarrollador. Entonces para llevar a cabo este paso escribiremos en el IDE Arduino un sencillo ejemplo que permite destellar el LED interno que posee la tarjeta Arduino UNO.

//Programa de ejemplo para destellar un LED
void setup()
{
   pinMode(LED_BUILTIN, OUTPUT);
}
void loop()
{
   digitalWrite(LED_BUILTIN, HIGH);
   delay(250);
   digitalWrite(LED_BUILTIN, LOW);
   delay(250);
}

Fig3. IDE Arduino


PASO 2 (Recuperar el código de la memoria de programa)

Para llevar a cabo este paso utilizaremos el programador UsbASP conectado el bus de datos al puerto ISP de la tarjeta Arduino UNO del cual deseamos recuperar el código de la memoria de programa. En la imagen de la figura 4, se observa la orientación del conector en el puerto ISP de la tarjeta. .

 

Fig4. Orientación de la conexión ISP

 

Una vez hecha la conexión y con el puerto serie debidamente identificado en el ordenador, procedemos a ejecutar en la linea de comandos la siguiente instrucción:

#avrdude -P /dev/ttyUSB0 -c usbasp -p m328p -U flash:r:flash.hex -U eeprom:r:eeprom.hex
avrdude: AVR device initialized and ready to accept instructions
Reading | ############################################ | 100% 0.00s
avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: reading flash memory:
Reading | ############################################ | 100% 16.70s
avrdude: writing output file "flash.hex"

avrdude: reading eeprom memory:
Reading | ############################################ | 100% 0.53s
avrdude: writing output file "eeprom.hex"

avrdude: safemode: Fuses OK (E:FE, H:DE, L:FF)
avrdude done.  Thank you.

Esta instrucción y sus parámetros nos permiten recuperar el contenido de la memoria de programa y datos del microcontrolador Atmega328 presente en la tarjeta Arduino UNO, luego los almacena en los ficheros flash.hex y eeprom.hex. El puerto serie utilizando para la comunicación con el programador UsbASP para mi caso es /dev/ttyUSB0, esto equivale al puerto COM01 en Windows. Notara también en las lineas de respuesta muestra que los valores presentes en los fusibles EFUSE, HFUSE y LFUSE son 0xFE, 0xDE y 0xFF respectivamente, siendo esta la configuración establecida por el cargador bootloader de Arduino, por lo que no deberán modificarse en posteriores actualizaciones al código.

PASO 3 (Restringir la lectura de la memoria de programa)

Este es el paso requerido que evitar la lectura del contenido de nuestra tarjeta Arduino UNO, que imposibilitara la copia de nuestro proyecto en otra tarjeta. La instrucción a ejecutar es:

#avrdude -P /dev/ttyUSB0 -c usbasp -p m328p -U lock:w:0xC0:m
avrdude: AVR device initialized and ready to accept instructions
Reading | ############################################ | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "0xC0"
avrdude: writing lock (1 bytes):
Writing | ############################################ | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0xC0:
avrdude: load data lock data from input file 0xC0:
avrdude: input file 0xC0 contains 1 bytes
avrdude: reading on-chip lock data:
Reading | ########################################### | 100% 0.00s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: safemode: Fuses OK (E:FE, H:DE, L:FF)
avrdude done.  Thank you.

El valor inicial del registro de bits LOCK para una tarjeta Arduino UNO es 0xCF(Configuración que protege al bootloader), entonces al cambiar a un valor 0xC0, los bits LB1-LB0 se programaran con 0, impidiendo así futuras lecturas de la memoria de programa del microcontrolador desde el puerto ISP, y los bits BLB02-BLB02 tambien se programaran en 0 para impedir el acceso al sector de aplicacion desde el cargador arduino . A manera comprobar esta restricción, intentaremos extraer nuevamente el contenido de la memoria de programa, ejecutando la siguiente instrucción:

#avrdude -P /dev/ttyUSB0 -c usbasp -p m328p -U flash:r:flash2.hex -U 

Aparentemente la respuesta a la instrucción nos muestra que el código se recupero con normalidad, pero haciendo una lista de los ficheros creados en la carpeta de trabajo, notaremos que el reciente archivo flash2.hex recuperado no posee contenido alguno.

Fig5. Lista de ficheros recuperados

Entones con la culminación de este paso hemos conseguido proteger el código de nuestro proyecto basado en la tarjeta UNO y la única manera de lograr quitar esta restricción es aplicando la instrucción chip erase que borrara toda la memoria del microcontrolador. 

PASO 4 (Cargar el código de programa a otra tarjeta UNO)

En este paso veremos como cargar el código de programa a una tarjeta UNO, a partir de los ficheros recuperados de otra tarjeta, este paso también nos servirá para restablecer los bits de protección de memoria en el registro LOCK al valor por defecto 0xCF.  

La instrucción requerida para llevar a cabo esta tarea es:

#avrdude -P /dev/ttyUSB0 -c usbasp -p m328p -e -V -U flash:w:flash.hex -U eeprom:w:eeprom.hex -U efuse:w:0xFE:m -U hfuse:w:0xDE:m -U lock:w:0xCF:m

avrdude: AVR device initialized and ready to accept instructions
Reading | ########################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file "flash.hex"
avrdude: input file flash.hex auto detected as raw binary
avrdude: writing flash (32768 bytes):
Writing | ########################################### | 100% 29.07s

avrdude: 32768 bytes of flash written
avrdude: reading input file "eeprom.hex"
avrdude: input file eeprom.hex auto detected as raw binary
avrdude: writing eeprom (1024 bytes):
Writing | ########################################### | 100% 10.81s

avrdude: 1024 bytes of eeprom written
avrdude: reading input file "0xFE"
avrdude: writing efuse (1 bytes):
Writing | ########################################### | 100% 0.00s

avrdude: 1 bytes of efuse written
avrdude: reading input file "0xDE"
avrdude: writing hfuse (1 bytes):
Writing | ########################################### | 100% 0.00s

avrdude: 1 bytes of hfuse written
avrdude: reading input file "0xCF"
avrdude: writing lock (1 bytes):
Writing | ########################################### | 100% 0.01s

avrdude: 1 bytes of lock written
avrdude: safemode: Fuses OK (E:FE, H:DE, L:FF)
avrdude done.  Thank you.

 

Ahora con los bits del registro LOCK restablecidos probaremos recuperar nuevamente el código de la memoria del microcontrolador

#avrdude -P /dev/ttyUSB0 -c usbasp -p m328p -U flash:r:flash3.hex

avrdude: AVR device initialized and ready to accept instructions
Reading | ########################################### | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading flash memory:
Reading | ########################################### | 100% 16.68s

avrdude: writing output file "flash3.hex"
avrdude: safemode: Fuses OK (E:FE, H:DE, L:FF)
avrdude done.  Thank you.

Fig6. Lista de ficheros recuperados

Conclusiones

Se recomienda cautela en la transcripción al momento de ejecutar las instrucciones, sobre todo cuando se aplica el parámetro -e con el que se procede a borrar la memoria y restablecer los fusibles del microcontrolador, tenga en cuenta que el bit SPIEN de HFUSE debe estar activado, caso contrario dejara al microcontrolador inhabitado para posteriores actualizaciones vía SPI. para mayores datos puede consultar el apartado 31.2 de la hoja de datos del microcontrolador Atmega328.

Estos son los valores por defecto que el cargado(Bootloader) Arduino utiliza en las tarjetas Atmega.

Modelo      UNO328   NANO328    MEGA2560  
-U efuse      0xFD      0xFD       0xFD
-U hfuse      0xDE      0xDA        0xD8
-U lfuse      0xFF       0xFF        0xFF
-U lock       0xCF      0xCF

Algunos enlaces de interés relacionados al tema de esta entrada:

Dejo el vídeo donde muestro como hacer la copia, protección y restauración de una placa Arduino UNO. 


Para finalizar, solo quiero agradecer tu visita al blog y cualquier consulta no dudes en escribirme a pablinzte@gmail.com

Pablo Zárate Arancibia

Ingeniero Electrónico

Santa Cruz - Bolivia

 


No hay comentarios.:

Publicar un comentario