diff --git a/core/SConscript.bootloader b/core/SConscript.bootloader index 59784547a..ae54a8a2d 100644 --- a/core/SConscript.bootloader +++ b/core/SConscript.bootloader @@ -20,7 +20,7 @@ if TREZOR_MODEL in ('1', ): ) Return() -FEATURES_WANTED = ["input", "rgb_led"] +FEATURES_WANTED = ["input", "rgb_led", "consumption_mask"] CCFLAGS_MOD = '' CPPPATH_MOD = [] diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 85f28fc80..374c47c18 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -18,7 +18,7 @@ FEATURE_FLAGS = { "SYSTEM_VIEW": False, } -FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d"] +FEATURES_WANTED = ["input", "sbu", "sd_card", "rgb_led", "dma2d", "consumption_mask"] CCFLAGS_MOD = '' CPPPATH_MOD = [] diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index c0c0421cc..6beae2f54 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -46,6 +46,9 @@ #ifdef USE_BUTTON #include "button.h" #endif +#ifdef USE_CONSUMPTION_MASK +#include "consumption_mask.h" +#endif #ifdef USE_RGB_LED #include "rgb_led.h" #endif @@ -340,6 +343,11 @@ int bootloader_main(void) { #ifdef USE_BUTTON button_init(); #endif + +#ifdef USE_CONSUMPTION_MASK + consumption_mask_init(); +#endif + #ifdef USE_RGB_LED rgb_led_init(); #endif diff --git a/core/embed/firmware/main.c b/core/embed/firmware/main.c index 8e5139433..f6b43f8b3 100644 --- a/core/embed/firmware/main.c +++ b/core/embed/firmware/main.c @@ -48,6 +48,9 @@ #ifdef USE_RGB_LED #include "rgb_led.h" #endif +#ifdef USE_CONSUMPTION_MASK +#include "consumption_mask.h" +#endif #ifdef USE_DMA2D #include "dma2d.h" #endif @@ -134,6 +137,10 @@ int main(void) { rgb_led_init(); #endif +#ifdef USE_CONSUMPTION_MASK + consumption_mask_init(); +#endif + #ifdef USE_I2C i2c_init(); #endif diff --git a/core/embed/trezorhal/boards/trezor_r_v10.h b/core/embed/trezorhal/boards/trezor_r_v10.h new file mode 100644 index 000000000..5a68428ab --- /dev/null +++ b/core/embed/trezorhal/boards/trezor_r_v10.h @@ -0,0 +1,51 @@ +#ifndef _TREZOR_R_V10_H +#define _TREZOR_R_V10_H + +#define USE_BUTTON 1 +#define USE_SBU 1 +#define USE_I2C 1 +#define USE_CONSUMPTION_MASK 1 + +#include "displays/vg-2864ksweg01.h" + +#define BTN_LEFT_PIN GPIO_PIN_10 +#define BTN_LEFT_PORT GPIOC +#define BTN_LEFT_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE +#define BTN_RIGHT_PIN GPIO_PIN_15 +#define BTN_RIGHT_PORT GPIOE +#define BTN_RIGHT_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE + +#define OLED_DC_PORT GPIOD +#define OLED_DC_PIN GPIO_PIN_0 // PD0 | Data/Command +#define OLED_DC_CLK_ENA __HAL_RCC_GPIOD_CLK_ENABLE +#define OLED_CS_PORT GPIOE +#define OLED_CS_PIN GPIO_PIN_4 // PE4 | SPI Select +#define OLED_CS_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define OLED_RST_PORT GPIOD +#define OLED_RST_PIN GPIO_PIN_1 // PD1 | Reset display +#define OLED_RST_CLK_ENA __HAL_RCC_GPIOD_CLK_ENABLE + +#define OLED_SPI SPI4 +#define OLED_SPI_AF GPIO_AF5_SPI4 +#define OLED_SPI_CLK_ENA __HAL_RCC_SPI4_CLK_ENABLE +#define OLED_SPI_SCK_PORT GPIOE +#define OLED_SPI_SCK_PIN GPIO_PIN_2 // PE2 | SPI SCK +#define OLED_SPI_SCK_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define OLED_SPI_MOSI_PORT GPIOE +#define OLED_SPI_MOSI_PIN GPIO_PIN_6 // PE6 | SPI MOSI +#define OLED_SPI_MOSI_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE + +#define I2C_COUNT 1 +#define I2C_INSTANCE_1 I2C2 +#define I2C_INSTANCE_1_CLK_EN __HAL_RCC_I2C2_CLK_ENABLE +#define I2C_INSTANCE_1_CLK_DIS __HAL_RCC_I2C2_CLK_DISABLE +#define I2C_INSTANCE_1_PIN_AF GPIO_AF4_I2C2 +#define I2C_INSTANCE_1_SDA_PORT GPIOB +#define I2C_INSTANCE_1_SDA_PIN GPIO_PIN_11 +#define I2C_INSTANCE_1_SDA_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE +#define I2C_INSTANCE_1_SCL_PORT GPIOB +#define I2C_INSTANCE_1_SCL_PIN GPIO_PIN_10 +#define I2C_INSTANCE_1_SCL_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE +#define I2C_INSTANCE_1_RESET_FLG RCC_APB1RSTR_I2C2RST + +#endif //_TREZOR_R_V10_H diff --git a/core/embed/trezorhal/consumption_mask.c b/core/embed/trezorhal/consumption_mask.c new file mode 100644 index 000000000..41cc919f2 --- /dev/null +++ b/core/embed/trezorhal/consumption_mask.c @@ -0,0 +1,108 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include STM32_HAL_H +#include "rng.h" + +#define SAMPLES 110 +#define TIMER_PERIOD 16640 // cca 10 KHz @ 180MHz + +#if defined BOARDLOADER +#error Not implemented for boardloader! +#endif + +#if defined BOOTLOADER +__attribute__((section(".buf"))) +#endif +uint32_t pwm_data[SAMPLES] = {0}; + +void consumption_mask_randomize() { + for (int i = 0; i < SAMPLES; i++) { + pwm_data[i] = rng_get() % TIMER_PERIOD; + } +} + +void consumption_mask_init(void) { + consumption_mask_randomize(); + + __HAL_RCC_GPIOC_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF3_TIM8; + GPIO_InitStructure.Pin = GPIO_PIN_6; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + __HAL_RCC_TIM8_CLK_ENABLE(); + TIM_HandleTypeDef TIM8_Handle; + TIM8_Handle.State = HAL_TIM_STATE_RESET; + TIM8_Handle.Instance = TIM8; + TIM8_Handle.Init.Period = TIMER_PERIOD; + TIM8_Handle.Init.Prescaler = 0; + TIM8_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + TIM8_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + TIM8_Handle.Init.RepetitionCounter = 0; + HAL_TIM_PWM_Init(&TIM8_Handle); + + TIM_OC_InitTypeDef TIM_OC_InitStructure; + TIM_OC_InitStructure.Pulse = 0; + TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM1; + TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_LOW; + TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE; + TIM_OC_InitStructure.OCNPolarity = TIM_OCNPOLARITY_HIGH; + TIM_OC_InitStructure.OCIdleState = TIM_OCIDLESTATE_SET; + TIM_OC_InitStructure.OCNIdleState = TIM_OCNIDLESTATE_SET; + HAL_TIM_PWM_ConfigChannel(&TIM8_Handle, &TIM_OC_InitStructure, TIM_CHANNEL_1); + + __HAL_RCC_DMA2_CLK_ENABLE(); + DMA_HandleTypeDef DMA_InitStructure = {0}; + DMA_InitStructure.Instance = DMA2_Stream1; + DMA_InitStructure.State = HAL_DMA_STATE_RESET; + DMA_InitStructure.Init.Channel = DMA_CHANNEL_7; + DMA_InitStructure.Init.Direction = DMA_MEMORY_TO_PERIPH; + DMA_InitStructure.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + DMA_InitStructure.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; + DMA_InitStructure.Init.MemBurst = DMA_MBURST_SINGLE; + DMA_InitStructure.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + DMA_InitStructure.Init.MemInc = DMA_MINC_ENABLE; + DMA_InitStructure.Init.Mode = DMA_CIRCULAR; + DMA_InitStructure.Init.PeriphBurst = DMA_PBURST_SINGLE; + DMA_InitStructure.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + DMA_InitStructure.Init.PeriphInc = DMA_PINC_DISABLE; + DMA_InitStructure.Init.Priority = DMA_PRIORITY_HIGH; + HAL_DMA_Init(&DMA_InitStructure); + + TIM4->CR2 |= TIM_CR2_MMS_1; // update event as TRGO + TIM8->CR2 |= TIM_CR2_CCPC; // preloading CCR register + TIM8->CR2 |= TIM_CR2_CCUS; // preload when TRGI + TIM8->DIER |= TIM_DMA_UPDATE; // allow DMA request from update event + TIM8->CCR1 = 0; + + HAL_Delay(1); + + DMA2->LIFCR |= 0xFC0; + DMA2_Stream1->M0AR = (uint32_t)pwm_data; + DMA2_Stream1->PAR = (uint32_t)&TIM8->CCR1; + DMA2_Stream1->NDTR = SAMPLES; + DMA2_Stream1->CR |= DMA_SxCR_EN; + + HAL_TIM_Base_Start(&TIM8_Handle); + HAL_TIM_PWM_Start(&TIM8_Handle, TIM_CHANNEL_1); +} diff --git a/core/embed/trezorhal/consumption_mask.h b/core/embed/trezorhal/consumption_mask.h new file mode 100644 index 000000000..d11fdabf9 --- /dev/null +++ b/core/embed/trezorhal/consumption_mask.h @@ -0,0 +1,9 @@ + +#ifndef CORE_CONSUMPTION_MASK_H +#define CORE_CONSUMPTION_MASK_H + +void consumption_mask_randomize(); + +void consumption_mask_init(void); + +#endif // CORE_CONSUMPTION_MASK_H diff --git a/core/embed/trezorhal/displays/vg-2864ksweg01.c b/core/embed/trezorhal/displays/vg-2864ksweg01.c index b95bc6383..83893731a 100644 --- a/core/embed/trezorhal/displays/vg-2864ksweg01.c +++ b/core/embed/trezorhal/displays/vg-2864ksweg01.c @@ -23,6 +23,10 @@ #include "display_interface.h" #include STM32_HAL_H +#ifdef USE_CONSUMPTION_MASK +#include "consumption_mask.h" +#endif + #define OLED_BUFSIZE (DISPLAY_RESX * DISPLAY_RESY / 8) #define OLED_OFFSET(x, y) (OLED_BUFSIZE - 1 - (x) - ((y) / 8) * DISPLAY_RESX) #define OLED_MASK(x, y) (1 << (7 - (y) % 8)) @@ -265,6 +269,11 @@ void display_refresh(void) { HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); // SPI select spi_send(s, 3); + +#if defined USE_CONSUMPTION_MASK && !defined BOARDLOADER + consumption_mask_randomize(); +#endif + HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET); // SPI deselect HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET); // set to DATA diff --git a/core/site_scons/boards/trezor_r_v10.py b/core/site_scons/boards/trezor_r_v10.py new file mode 100644 index 000000000..a5ec8c94a --- /dev/null +++ b/core/site_scons/boards/trezor_r_v10.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from . import get_hw_model_as_number + + +def configure( + env: dict, + features_wanted: list[str], + defines: list[str | tuple[str, str]], + sources: list[str], +) -> list[str]: + features_available: list[str] = [] + hw_model = get_hw_model_as_number("T2B1") + hw_revision = 10 + board = "trezor_r_v10.h" + display = "vg-2864ksweg01.c" + + defines += [f'TREZOR_BOARD=\\"boards/{board}\\"'] + defines += [f"HW_MODEL={hw_model}"] + defines += [f"HW_REVISION={hw_revision}"] + sources += [f"embed/trezorhal/displays/{display}"] + + sources += [f"embed/trezorhal/i2c.c"] + + if "input" in features_wanted: + sources += ["embed/trezorhal/button.c"] + features_available.append("button") + + if "sbu" in features_wanted: + sources += ["embed/trezorhal/sbu.c"] + features_available.append("sbu") + + if "consumption_mask" in features_wanted: + sources += ["embed/trezorhal/consumption_mask.c"] + + env.get("ENV")["TREZOR_BOARD"] = board + + return features_available diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py index 695a8bd65..40672bf25 100644 --- a/core/site_scons/tools.py +++ b/core/site_scons/tools.py @@ -3,7 +3,7 @@ from __future__ import annotations from pathlib import Path import subprocess -from boards import trezor_1, trezor_r_v3, trezor_r_v4, trezor_t, trezor_r_v6, discovery +from boards import trezor_1, trezor_r_v3, trezor_r_v4, trezor_t, trezor_r_v6, trezor_r_v10, discovery HERE = Path(__file__).parent.resolve() @@ -31,7 +31,7 @@ def configure_board( defines: list[str | tuple[str, str]], sources: list[str], ): - model_r_version = 6 + model_r_version = 10 if model in ("1",): return trezor_1.configure(env, features_wanted, defines, sources) @@ -42,8 +42,10 @@ def configure_board( return trezor_r_v3.configure(env, features_wanted, defines, sources) elif model_r_version == 4: return trezor_r_v4.configure(env, features_wanted, defines, sources) - else: + elif model_r_version == 6: return trezor_r_v6.configure(env, features_wanted, defines, sources) + elif model_r_version == 10: + return trezor_r_v10.configure(env, features_wanted, defines, sources) elif model in ('DISC1',): return discovery.configure(env, features_wanted, defines, sources) else: