Autor Tema: Bootloader Encriptado para STM32 con uTasker  (Leído 6830 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Bootloader Encriptado para STM32 con uTasker
« en: 30 de Septiembre de 2017, 10:08:42 »

Después de haber instalado y configurado con éxito el bootoader encriptado uTasker para los Kinetis, me llegó el momento de hacer lo mismo para los STM32, aprovechando que tengo en marcha el proyecto de la ruleta para un cliente, y otro proyecto que también usa un STM32F405, para otro cliente.

En principio uTasker es muy similar para los STM32, aunque por ahora noto algunas diferencias (un parámetro que no localizo), me da la sensación que el autor se ha centrado más en desarrollar el producto para los Kinetis, pero vamos a ver que sale. Para los STM32 no parece estár disponible el proyecto para ser abierto con Eclipse, una pena, porque es mi preferido. De las opciones gratuitas está Coocox o compilarlo a pelo con el Makefile y editarlo con cualquier editor, por ejemplo con Geany. De momento he optado por abrir el proyecto con Coocox.

0.- El proyecto, se descarga de este enlace, está completo con todos los fuentes.
http://www.utasker.com/forum/index.php?action=dlattach;topic=1697.0;attach=651

Como yo lo voy a documentar con Coocox, tenemos que tenerlo instalado, si no bajarlo de aquí.
http://coocox.org/download.php?downIndex=CoIDE&id=20


1.- Descomprimimos uTasker, nos vamos a esta carpeta y pinchamos sobre el proyecto, que se abrirá en Coocox
\uTaskerV1.4.3_STM32\Applications\uTaskerSerialBoot\CooCox\uTaskerSerialBoot.coproj


2.- En el proyecto hay 3 archivos clave a configurar para adecuar el bootloader.
config.h --> Seleccionamos tipo de placa/procesador, y drivers a usar (SD, USB, Ethernet, Serie...).
Loader.h --> Configuramos la clave de encriptacion a usar y el nombre del archivo a cargar
app_hw_stm32.h --> Define el hardware, Frecuencia cuarzo Reloj/PLL, y también los LED/Switches a usar


3.- Empezamos configurando el fichero config.h
En el bootloder para los Kinetis hay mucha más variedad de micros a elegir, en los STM32 se limita a estos, pero se puede modificar fácilmente para añadir otros, si hiciera falta, tocando básicamente la configuración en app_hw_stm32.h. De estos elegimos uno, en mi caso me interesa trabajar con los STM32405 y STM32M407, así que elijo ST_MB997A y comento el resto.
//#define STM3210C_EVAL   // evaluation board with STM32F107VCT
//#define STM3240G_EVAL    // evaluation board with STM32F407IGH6
//#define ST_MB913C_DISCOVERY  // discovery board with STM32F100RB
#define ST_MB997A_DISCOVERY    // discovery board with STM32F407VGT6, Usar esta con STM32F405/407

Si vamos a cargar el firmware por tarjeta SD, que es mi caso, habilitamos este define, por omisión creo que está comentado.
#define SDCARD_SUPPORT

Si nuestro bootloader no va a usar USB ni Ethernet, poniendo estos defines se "desactivan" y el objeto resultante reduce su tamaño una barbaridad, de 110K a solo unos 31K (deshabilitando también el puerto serie). Esto solo afecta al bootloader, no a la aplicación de usuario.
#define DEVICE_WITHOUT_USB // Desactivo el USB
#define DEVICE_WITHOUT_ETHERNET // Desactivo Ethernet


Y creo que si nuestro bootloader no va a usar puerto serie, hay que comentar este define, y el objeto se reduce aún más.
// #define SERIAL_INTERFACE


4.- Ahora nos vamos al fichero Loader.h.
Aquí básicamente se configuran los parámetros de encriptación del firmware, y el nombre que tendrá el fichero a cargar por el bootloader.

Si cargamos con tarjeta SD y queremos encriptar, habilitamos este define:
#define ENCRYPTED_CARD_CONTENT

Los parámetros de encriptación son estos y cada uno los puede configurar a su gusto, cambiando los códigos en hexadecimal para personalizar la clave de encriptación, y el nombre que tendrá el fichero de firmware del usuario que buscará el bootloader para cargarlo.

#define NEW_SOFTWARE_FILE   "sd_card_enc.bin"
#define VALID_VERSION_MAGIC_NUMBER   0x651d
#define _SECRET_KEY  {0xb7, 0x48, 0xb6, 0x53, 0x11, 0x24}
static const unsigned char ucDecrypt[] = {0xff, 0x25, 0xa7, 0x88, 0xf2, 0xe6, 0x81, 0x33, 0x87, 0x77};
#define KEY_PRIME  0xafe1  // never set to 0
#define CODE_OFFSET  0xc298  // ensure that this value is a multiple of the smallest flash programming entity size


5.- Y llegamos al último archivo a configurar, el app_hw_stm32.h
Aquí se define el hardware, básicamente la configuración del Reloj/PLL del micro que usemos y los puertos de los LED y pulsadores que queramos usar.

Si podemos usar los microcontroladores definidos ya en el config.h, no hará falta tocar nada del reloj y el PLL, ya está todo parametrizado. Pero si quisieramos usar un micro no configurado, podemos partir de uno ya definido y modificarlo, yo lo tuve que hacer con los Kinetis para poder usar los MK66.

Por ejemplo al seleccionar en config.h el define que indiqué para trabajar con los STM32F407 y 405 se habilita esta configuración de reloj y PLL. No tiene mayor misterio, cuarzo a 8Mhz, PLL configurado para llevar el reloj a 168Mhz. También se define el tamaño de flash y ram, entre otras cosas

#define CRYSTAL_FREQ        8000000
//#define DISABLE_PLL     // run from clock source directly
//#define USE_HSI_CLOCK    // use internal HSI clock source
#define PLL_INPUT_DIV   4  // 2..64 - should set the input to pll in the range 1..2MHz (with preference near to 2MHz)
#define PLL_VCO_MUL  168     // 64 ..432 where VCO must be 64..432MHz
#define PLL_POST_DIVIDE   2    // post divide VCO by 2, 4, 6, or 8 to get the system clock speed
#define PIN_COUNT     PIN_COUNT_100_PIN
#define PACKAGE_TYPE   PACKAGE_LQFP
#define _STM32F4XX
#define SIZE_OF_RAM   (128 * 1024)   // 128k SRAM
#define SIZE_OF_CCM   (64 * 1024)     // 64k Core Coupled Memory
#define SIZE_OF_FLASH   (1024 * 1024)   // 1M FLASH
#define SUPPLY_VOLTAGE  SUPPLY_2_7__3_6  // power supply is in the range 2.7V..3.6V
#define PCLK1_DIVIDE  4
#define PCLK2_DIVIDE  2
#define HCLK_DIVIDE   1


En estos parmámetros se definen los puertos a usar para LEDs y pulsadores. En mi caso no uso los pulsadores, porque configuro el bootloader para que siempre entre automáticamente nada más arrancar, compruebe si hay tarjeta SD y firmware para cargar, si lo hay lo carga y salta a la aplicación de usuario, y si no lo hay salta a la aplicación de usuario (si hay alguna cargada ya).

#define USER_KEY_BUTTON            PORTA_BIT0
#define LED1      PORTD_BIT12     // green LED
#define LED2      PORTD_BIT13     // orange LED
#define LED3      PORTD_BIT14     // red LED
#define LED4      PORTD_BIT15     // blue LED
#define BLINK_LED   LED1
#define INIT_WATCHDOG_DISABLE()  _CONFIG_PORT_INPUT(A, (USER_KEY_BUTTON), (FLOATING_INPUT)) // PA0 input pull-down
#define WATCHDOG_DISABLE()  (_READ_PORT_MASK(A, (USER_KEY_BUTTON))) // disable watchdog by holding user button
#define INIT_WATCHDOG_LED()  _CONFIG_PORT_OUTPUT(D, BLINK_LED, (OUTPUT_SLOW | OUTPUT_PUSH_PULL))
#define TOGGLE_WATCHDOG_LED()  _TOGGLE_PORT(D, BLINK_LED)        // blink the LED, if set as output


Yo el watchdog lo fuerzo activado siempre, sin vinculación con un pulsador, modificando el define anterior a 0:
#define WATCHDOG_DISABLE() 0

o si lo quisieramos tener permanentemente desactivado, lo pondríamos a 1
#define WATCHDOG_DISABLE() 1

Parámetro para forzar el modo boot al arrancar. Este parámetro que sirve para entrar en modo boot al arrancar, en el fuente está vinculado al estado de un pulsador asignado por el usuario, pero yo lo fuerzo a entrar siempre sin pulsar nada, cambiándo el define a 1.

Como viene por omisión, salta al modo boot, manteniendo pulsado un botón.
#define FORCE_BOOT()  (_READ_PORT_MASK(A, (USER_KEY_BUTTON))) // hold user key at reset to force boot loader mode

Modificado por mi, para entrar siempre al modo boot en el arranque, sin pulsar nada
#define FORCE_BOOT()  1

Otro parámetro a configurar, este indica si tras cargar el firmware, permanecera en modo boot, o saltará automáticamente a la aplicación de usuario. Si no salta automáticamente, hay que vincular este define al estado de un pulsador para saltar al apretarlo. Lo tengo puesto a 0, para que salte automáticamente.

#define RETAIN_LOADER_MODE()    0  // force retaining boot loader mode after update


6.- Con todo configurado, ya solo queda compilar y grabar en el micro. El firmware de usuario hay que compilarlo para que arranque en la dirección 0x8000 (modificando el Linker Script).

Para encriptar el firmware, hace falta la utilidad uTaskerConvert.exe que está en la carpeta \uTaskerV1.4.3_STM32\Tools. Yo me creo un fichero BAT, que convierte el HEX a BIN y lo encripta. Con las claves de encriptación que vienen en el fuente por omisión, si nuestro compilado se llamase fichero.hex y el archivo encriptado lo quisieramos llamar fichero.bin, este sería el .BAT a crear.

objcopy --input-target=ihex --output-target=binary fichero.hex inter.bin
uTaskerConvert.exe inter.bin fichero.bin -0x651d -b748b6531124 -ff25a788f2e681338777 -afe1 -c298
del inter.bin


Hay un parámetro más que por ahora no lo he localizado, y que si aparece en el bootloader para los Kinetis, y que sirve para indicar que el bootloader borre el fichero de la tarjeta SD una vez lo haya cargado a la Flash. Le he preguntado al autor, a ver si me resuelve la duda.


« Última modificación: 30 de Septiembre de 2017, 11:37:32 por planeta9999 »

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #1 en: 06 de Marzo de 2018, 08:46:19 »
Excelente tutorial, planeta.
Me va a tocar implementarlo en un STM32 así que lo seguiré paso a paso e imagino que apareceré por aquí con dudas.
Muchas gracias

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #2 en: 06 de Marzo de 2018, 10:24:34 »
 
OK, a ver que tal te va, yo solo lo tengo funcionando en Kinetis. Hay alguna pequeña diferencia en algún parámetro que no está implementado, pero que se podría meter mirando en los fuentes de Kinetis.

Aquí puedes ver algunas dudas que le planteé al autor, por las diferencias entre la versión para Kinetis y para STM32.
http://www.utasker.com/forum/index.php?PHPSESSID=67a0n43tbah2jtk6fse7eht856&topic=1958.0

Todo lo que ha publicado para STM32, está en este enlace, con la última versión a 2016, creo que el ZIP lleva password, si lo necesitas te lo paso por privado.
http://www.utasker.com/stm32/developers.html
http://www.utasker.com/stm32/dev_sw/STM32_uTaskerV1.4.9_pre_20.12.2016.zip

Documentación en PDF para STM32
http://www.utasker.com/docs/STM32/uTaskerV1.4_STM32_Developers_Document.pdf
« Última modificación: 06 de Marzo de 2018, 10:31:03 por planeta9999 »

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #3 en: 04 de Febrero de 2019, 13:39:25 »
Rescato el tema.

No consigo descargar Coocox porque su web está caída.

Y al importar el fichero en Atollic TrueStudio para intentar cambiarlo a un STM32F103, no consigo que compile. No paran de salirme errores de referencia y ficheros que faltan.
¿Qué me aconsejas?

Gracias

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #5 en: 05 de Febrero de 2019, 03:38:19 »
Muchas gracias.

Ya lo he instalado, pero sigo sin poder compilar uTasker. Me da un par de errores, que son los mismos que salían en Atollic:
Código: [Seleccionar]
..\uTasker\Hardware\STM32\STM32.c:3813:124: error: 'PLL_Q_VALUE' undeclared (first use in this function)
..\uTasker\Hardware\STM32\STM32.c:3806:20: error: 'RCC_APB2ENR_SDIOEN' undeclared (first use in this function); did you mean 'RCC_APB2ENR_SPI1EN'?

Seguro que se me está escapando alguna tontería, pero no lo saco

Desconectado AccioRw

  • PIC16
  • ***
  • Mensajes: 165
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #6 en: 05 de Febrero de 2019, 05:55:16 »
Esos errores me suenan de haberlos tenido alguna vez (errores similares cambiando los nombres solamente) en el System Workbench (Eclipse AC6) creo que fueron por no tener bien puesto las librerias en "Properties -> C/C++ Build -> Settings y aquí dentro seleccionando en Tool Settings la carpeta includes.
EDITO:Perdon, el problema fue en "C/C++ General" dentro del apartado Paths and Symbols

No sé si tendrá algo que ver con tu caso pero quizas te pueda ayudar a saber por donde pueden ir los tiros  :oops:
« Última modificación: 05 de Febrero de 2019, 06:26:31 por AccioRw »

Desconectado AccioRw

  • PIC16
  • ***
  • Mensajes: 165
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #7 en: 05 de Febrero de 2019, 06:13:32 »
Le voy a intentar dedicar un rato por las noches al salir del trabajo e intento portarlo a Eclipse AC6, tengo el mismo micro (stm32F103) en una placa de desarrollo tipo arduino nano (una stm32l432kc) así que incluso puedo probarlo fisicamente...
Como querrias utilizar el bootloader Nocturno, serie, usb... ?

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #8 en: 05 de Febrero de 2019, 06:29:16 »
Muchas gracias.

Ya lo he instalado, pero sigo sin poder compilar uTasker. Me da un par de errores, que son los mismos que salían en Atollic:
Código: [Seleccionar]
..\uTasker\Hardware\STM32\STM32.c:3813:124: error: 'PLL_Q_VALUE' undeclared (first use in this function)
..\uTasker\Hardware\STM32\STM32.c:3806:20: error: 'RCC_APB2ENR_SDIOEN' undeclared (first use in this function); did you mean 'RCC_APB2ENR_SPI1EN'?

Seguro que se me está escapando alguna tontería, pero no lo saco

Lo desconozco, porque solo puse en marcha la versión para Kinetis. Se lo puedes preguntar directamente a su autor, en el foro de uTasker para STM32.

http://www.utasker.com/forum/index.php?board=5.0

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #9 en: 05 de Febrero de 2019, 08:01:00 »
Le voy a intentar dedicar un rato por las noches al salir del trabajo e intento portarlo a Eclipse AC6, tengo el mismo micro (stm32F103) en una placa de desarrollo tipo arduino nano (una stm32l432kc) así que incluso puedo probarlo fisicamente...
Como querrias utilizar el bootloader Nocturno, serie, usb... ?

Por tarjeta SD, pero vamos, que si compila ya me doy por satisfecho porque podré seguir trabajando y adaptándolo.


Lo desconozco, porque solo puse en marcha la versión para Kinetis. Se lo puedes preguntar directamente a su autor, en el foro de uTasker para STM32.

http://www.utasker.com/forum/index.php?board=5.0

Gracias, le consultaré.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #10 en: 05 de Febrero de 2019, 15:33:26 »

Acabo de compilar el proyecto, sin tocar nada, todo tal cual está descargado de los enlaces y con el Coocox que he puesto, y a mi no me da ningún error, compila sin problemas.


« Última modificación: 05 de Febrero de 2019, 15:54:53 por planeta9999 »

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18271
    • MicroPIC
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #11 en: 05 de Febrero de 2019, 16:03:10 »
Ah, ese sí que compila. Pero yo lo estaba intentando con el uTaskerSerialBoot que tú habías indicado en el primer post.

Lo intento con este otro. Gracias

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #12 en: 05 de Febrero de 2019, 16:13:54 »
 
Ya veo, es al cambiar el micro, si elijo el F107 salen esos errores.

Código: C++
  1. #define STM3210C_EVAL                                                  // evaluation board with STM32F107VCT
  2. //#define STM3240G_EVAL                                                  // evaluation board with STM32F407IGH6
  3. //#define ST_MB913C_DISCOVERY                                            // discovery board with STM32F100RB
  4. // #define ST_MB997A_DISCOVERY                                              // discovery board with STM32F407VGT6
  5. #if defined STM3210C_EVAL
  6.     #define TARGET_HW       "STM3210C-EVAL (STM32F107VCT)"
  7.     #define OUR_HEAP_SIZE (HEAP_REQUIREMENTS)((24 * 1024) * MEM_FACTOR)  // we have the LAN buffers in HEAP and big RX/TX


Esos defines que dan error (por no quedar definidos para esa configuración de micro) están en el STM32.h, supongo que todo está relacionado con la configuración del reloj, parece que de PLL, y del controlador SDIO. Lo que me extraña es que de error, porque por los IF que tiene definidos, si no se cumple ninguno le asigna un valor de 15 a PLL_Q_VALUE

Código: C++
  1. #if defined USB_INTERFACE                                        // if USB is to be used the ring clock frequency must be 48MHz
  2.             #define PLL_Q_VALUE   (PLL_VCO_FREQUENCY/48000000)
  3.             #if (PLL_Q_VALUE < 2) || (PLL_Q_VALUE > 15)
  4.                 #error "Illegal divide value for USB clock!!"
  5.             #elif (PLL_VCO_FREQUENCY/PLL_Q_VALUE) != 48000000
  6.                 #error "48MHz USB clock not possible!!"
  7.             #endif
  8.         #elif defined RING_POST_DIVIDE
  9.             #if RING_POST_DIVIDE >= 2 && RING_POST_DIVIDE <= 15
  10.                 #define PLL_Q_VALUE  RING_POST_DIVIDE
  11.                 #if (PLL_VCO_FREQUENCY/RING_POST_DIVIDE) > 48000000
  12.                     #error "Ring clock (SDIOCLK) too high (<= 48MHz)"
  13.                 #endif
  14.             #else
  15.                 #error "RING_POST_DIVIDE must be between 2 and 15!!"
  16.             #endif
  17.         #else
  18.             #define PLL_Q_VALUE  15                                      // set lowest speed when no USB
  19.         #endif


Y el define de RCC_APB2ENR_SDIOEN también está en el mismo fuente, condicionado por un IF, solo para micros F2 y F4. Si hemos seleccionado un F107 se queda sin definir.

Código: C++
  1. // Reset and clock control
  2. //
  3. #if defined _STM32F2XX || defined _STM32F4XX
  4.       #define RCC_APB2ENR_SDIOEN             0x00000800

« Última modificación: 05 de Febrero de 2019, 16:29:42 por planeta9999 »

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #13 en: 14 de Junio de 2019, 19:10:14 »
 
uTasker se ha actualizado bastante desde la anterior versión. Ahora está en un Github, y se han combinado los fuentes para ofrecer Kinetis y STM32 en un solo paquete. Yo lo quiero probar para un STM32F746, dentro de los fuentes lleva una configuración para la placa de evaluación de ese micro.

https://github.com/uTasker/uTasker-Kinetis

Desconectado AccioRw

  • PIC16
  • ***
  • Mensajes: 165
Re:Bootloader Encriptado para STM32 con uTasker
« Respuesta #14 en: 14 de Junio de 2019, 19:14:15 »
Yo me quedé atascado con este tema y no fui capaz de llegar a nada, entre el poco tiempo que me queda por las noches después del trabajo y demás al final lo dejé por imposible o por darle más prioridad a otros temas que me han salido con mas prisas, aunque realmente también este tema es uno de los que me afecta y me guste o no tendré que darle vueltas…
En fin, gracias por avisar de las nuevas versiones Planeta  ((:-))