mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-26 08:08:51 +00:00
feat(core): add RGB LED driver for Model R
This commit is contained in:
parent
0112d0135a
commit
c33f92bd72
1
core/.changelog.d/2300.added
Normal file
1
core/.changelog.d/2300.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add RGB LED for Model R
|
@ -139,6 +139,7 @@ env.Replace(
|
|||||||
'vendor/micropython/lib/cmsis/inc',
|
'vendor/micropython/lib/cmsis/inc',
|
||||||
] + CPPPATH_MOD,
|
] + CPPPATH_MOD,
|
||||||
CPPDEFINES=[
|
CPPDEFINES=[
|
||||||
|
'BOARDLOADER',
|
||||||
'TREZOR_MODEL_'+TREZOR_MODEL,
|
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||||
CPU_MODEL,
|
CPU_MODEL,
|
||||||
'USE_HAL_DRIVER',
|
'USE_HAL_DRIVER',
|
||||||
|
@ -71,6 +71,7 @@ SOURCE_MOD += [
|
|||||||
SOURCE_STMHAL = [
|
SOURCE_STMHAL = [
|
||||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c',
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c',
|
||||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c',
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c',
|
||||||
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c',
|
||||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c',
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c',
|
||||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c',
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c',
|
||||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c',
|
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c',
|
||||||
@ -125,6 +126,7 @@ SOURCE_TREZORHAL = [
|
|||||||
|
|
||||||
if TREZOR_MODEL in ('R'):
|
if TREZOR_MODEL in ('R'):
|
||||||
SOURCE_TREZORHAL.append('embed/trezorhal/button.c')
|
SOURCE_TREZORHAL.append('embed/trezorhal/button.c')
|
||||||
|
SOURCE_TREZORHAL.append('embed/trezorhal/rgb_led.c')
|
||||||
if TREZOR_MODEL in ('T',):
|
if TREZOR_MODEL in ('T',):
|
||||||
SOURCE_TREZORHAL.append('embed/trezorhal/touch.c')
|
SOURCE_TREZORHAL.append('embed/trezorhal/touch.c')
|
||||||
|
|
||||||
@ -174,6 +176,7 @@ env.Replace(
|
|||||||
'vendor/nanopb',
|
'vendor/nanopb',
|
||||||
] + CPPPATH_MOD,
|
] + CPPPATH_MOD,
|
||||||
CPPDEFINES=[
|
CPPDEFINES=[
|
||||||
|
'BOOTLOADER',
|
||||||
'TREZOR_MODEL_'+TREZOR_MODEL,
|
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||||
CPU_MODEL,
|
CPU_MODEL,
|
||||||
'USE_HAL_DRIVER',
|
'USE_HAL_DRIVER',
|
||||||
|
@ -384,7 +384,12 @@ if TREZOR_MODEL in ('T',):
|
|||||||
'embed/trezorhal/sdcard.c',
|
'embed/trezorhal/sdcard.c',
|
||||||
'embed/trezorhal/touch.c',
|
'embed/trezorhal/touch.c',
|
||||||
]
|
]
|
||||||
elif TREZOR_MODEL in ('1', 'R'):
|
elif TREZOR_MODEL in ('R',):
|
||||||
|
SOURCE_TREZORHAL += [
|
||||||
|
'embed/trezorhal/button.c',
|
||||||
|
'embed/trezorhal/rgb_led.c',
|
||||||
|
]
|
||||||
|
elif TREZOR_MODEL in ('1',):
|
||||||
SOURCE_TREZORHAL += [
|
SOURCE_TREZORHAL += [
|
||||||
'embed/trezorhal/button.c',
|
'embed/trezorhal/button.c',
|
||||||
]
|
]
|
||||||
@ -470,6 +475,7 @@ env.Replace(
|
|||||||
'vendor/micropython/lib/cmsis/inc',
|
'vendor/micropython/lib/cmsis/inc',
|
||||||
] + CPPPATH_MOD,
|
] + CPPPATH_MOD,
|
||||||
CPPDEFINES=[
|
CPPDEFINES=[
|
||||||
|
'FIRMWARE',
|
||||||
'TREZOR_MODEL_'+TREZOR_MODEL,
|
'TREZOR_MODEL_'+TREZOR_MODEL,
|
||||||
CPU_MODEL,
|
CPU_MODEL,
|
||||||
'USE_HAL_DRIVER',
|
'USE_HAL_DRIVER',
|
||||||
|
1
core/embed/bootloader/.changelog.d/2300.added
Normal file
1
core/embed/bootloader/.changelog.d/2300.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add RGB LED for Model R
|
@ -34,6 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined TREZOR_MODEL_R
|
#if defined TREZOR_MODEL_R
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
|
#include "rgb_led.h"
|
||||||
#endif
|
#endif
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -255,6 +256,7 @@ int main(void) {
|
|||||||
|
|
||||||
#if defined TREZOR_MODEL_R
|
#if defined TREZOR_MODEL_R
|
||||||
button_init();
|
button_init();
|
||||||
|
rgb_led_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mpu_config_bootloader();
|
mpu_config_bootloader();
|
||||||
|
@ -49,6 +49,11 @@ SECTIONS {
|
|||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >CCMRAM
|
} >CCMRAM
|
||||||
|
|
||||||
|
.buf : ALIGN(4) {
|
||||||
|
*(.buf*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} >SRAM
|
||||||
|
|
||||||
.stack : ALIGN(8) {
|
.stack : ALIGN(8) {
|
||||||
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
|
. = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */
|
||||||
} >CCMRAM
|
} >CCMRAM
|
||||||
|
@ -358,8 +358,10 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t chunk_size = 0;
|
static uint32_t chunk_size = 0;
|
||||||
// SRAM is unused, so we can use it for chunk buffer
|
|
||||||
uint8_t *const chunk_buffer = (uint8_t *const)0x20000000;
|
__attribute__((section(".buf"))) uint32_t chunk_buffer[IMAGE_CHUNK_SIZE / 4];
|
||||||
|
|
||||||
|
#define CHUNK_BUFFER_PTR ((const uint8_t *const)&chunk_buffer)
|
||||||
|
|
||||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||||
static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
|
static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
|
||||||
@ -375,7 +377,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
|
|||||||
|
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
// clear chunk buffer
|
// clear chunk buffer
|
||||||
memset(chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE);
|
memset((uint8_t *)&chunk_buffer, 0xFF, IMAGE_CHUNK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t chunk_written = offset;
|
uint32_t chunk_written = offset;
|
||||||
@ -390,7 +392,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
|
|||||||
}
|
}
|
||||||
// read data
|
// read data
|
||||||
if (!pb_read(
|
if (!pb_read(
|
||||||
stream, (pb_byte_t *)(chunk_buffer + chunk_written),
|
stream, (pb_byte_t *)(CHUNK_BUFFER_PTR + chunk_written),
|
||||||
(stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) {
|
(stream->bytes_left > BUFSIZE) ? BUFSIZE : stream->bytes_left)) {
|
||||||
chunk_size = 0;
|
chunk_size = 0;
|
||||||
return false;
|
return false;
|
||||||
@ -481,14 +483,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
if (headers_offset == 0) {
|
if (headers_offset == 0) {
|
||||||
// first block and headers are not yet parsed
|
// first block and headers are not yet parsed
|
||||||
vendor_header vhdr;
|
vendor_header vhdr;
|
||||||
if (sectrue != load_vendor_header_keys(chunk_buffer, &vhdr)) {
|
if (sectrue != load_vendor_header_keys(CHUNK_BUFFER_PTR, &vhdr)) {
|
||||||
MSG_SEND_INIT(Failure);
|
MSG_SEND_INIT(Failure);
|
||||||
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
||||||
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header");
|
MSG_SEND_ASSIGN_STRING(message, "Invalid vendor header");
|
||||||
MSG_SEND(Failure);
|
MSG_SEND(Failure);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if (sectrue != load_image_header(chunk_buffer + vhdr.hdrlen,
|
if (sectrue != load_image_header(CHUNK_BUFFER_PTR + vhdr.hdrlen,
|
||||||
FIRMWARE_IMAGE_MAGIC,
|
FIRMWARE_IMAGE_MAGIC,
|
||||||
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m,
|
FIRMWARE_IMAGE_MAXSIZE, vhdr.vsig_m,
|
||||||
vhdr.vsig_n, vhdr.vpub, &hdr)) {
|
vhdr.vsig_n, vhdr.vpub, &hdr)) {
|
||||||
@ -574,7 +576,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
|
if (sectrue != check_single_hash(hdr.hashes + firmware_block * 32,
|
||||||
chunk_buffer + headers_offset,
|
CHUNK_BUFFER_PTR + headers_offset,
|
||||||
chunk_size - headers_offset)) {
|
chunk_size - headers_offset)) {
|
||||||
if (firmware_upload_chunk_retry > 0) {
|
if (firmware_upload_chunk_retry > 0) {
|
||||||
--firmware_upload_chunk_retry;
|
--firmware_upload_chunk_retry;
|
||||||
@ -594,7 +596,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
|
|||||||
|
|
||||||
ensure(flash_unlock_write(), NULL);
|
ensure(flash_unlock_write(), NULL);
|
||||||
|
|
||||||
const uint32_t *const src = (const uint32_t *const)chunk_buffer;
|
const uint32_t *const src = (const uint32_t *const)CHUNK_BUFFER_PTR;
|
||||||
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) {
|
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) {
|
||||||
ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block],
|
ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block],
|
||||||
i * sizeof(uint32_t), src[i]),
|
i * sizeof(uint32_t), src[i]),
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
#include "bl_check.h"
|
#include "bl_check.h"
|
||||||
#include "board_capabilities.h"
|
#include "board_capabilities.h"
|
||||||
#include "button.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compiler_traits.h"
|
#include "compiler_traits.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
@ -45,6 +44,13 @@
|
|||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "mpu.h"
|
#include "mpu.h"
|
||||||
#include "random_delays.h"
|
#include "random_delays.h"
|
||||||
|
#ifdef TREZOR_MODEL_R
|
||||||
|
#include "rgb_led.h"
|
||||||
|
#endif
|
||||||
|
#if defined TREZOR_MODEL_R || defined TREZOR_MODEL_1
|
||||||
|
#include "button.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SYSTEM_VIEW
|
#ifdef SYSTEM_VIEW
|
||||||
#include "systemview.h"
|
#include "systemview.h"
|
||||||
#endif
|
#endif
|
||||||
@ -100,6 +106,7 @@ int main(void) {
|
|||||||
#if defined TREZOR_MODEL_R
|
#if defined TREZOR_MODEL_R
|
||||||
button_init();
|
button_init();
|
||||||
display_clear();
|
display_clear();
|
||||||
|
rgb_led_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined TREZOR_MODEL_T
|
#if defined TREZOR_MODEL_T
|
||||||
|
@ -274,6 +274,8 @@ fn generate_trezorhal_bindings() {
|
|||||||
.allowlist_function("button_sequence_to_word")
|
.allowlist_function("button_sequence_to_word")
|
||||||
// random
|
// random
|
||||||
.allowlist_function("random_uniform")
|
.allowlist_function("random_uniform")
|
||||||
|
// rgb led
|
||||||
|
.allowlist_function("rgb_led_set_color")
|
||||||
// time
|
// time
|
||||||
.allowlist_function("hal_delay")
|
.allowlist_function("hal_delay")
|
||||||
.allowlist_function("hal_ticks_ms");
|
.allowlist_function("hal_ticks_ms");
|
||||||
|
@ -4,6 +4,8 @@ pub mod common;
|
|||||||
pub mod display;
|
pub mod display;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
|
#[cfg(feature = "model_tr")]
|
||||||
|
pub mod rgb_led;
|
||||||
pub mod slip39;
|
pub mod slip39;
|
||||||
|
|
||||||
#[cfg(not(feature = "micropython"))]
|
#[cfg(not(feature = "micropython"))]
|
||||||
|
7
core/embed/rust/src/trezorhal/rgb_led.rs
Normal file
7
core/embed/rust/src/trezorhal/rgb_led.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use super::ffi;
|
||||||
|
|
||||||
|
pub fn set_color(color: u32) {
|
||||||
|
unsafe {
|
||||||
|
ffi::rgb_led_set_color(color);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "rgb_led.h"
|
||||||
#include "secbool.h"
|
#include "secbool.h"
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
|
|
||||||
|
168
core/embed/trezorhal/rgb_led.c
Normal file
168
core/embed/trezorhal/rgb_led.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implements driver for IN-PI15TAT5R5G5B 1515 RGB LED 4-Pin with Integrated IC
|
||||||
|
*
|
||||||
|
* The communication protocol prescribes encoding of 0 as a short pulse
|
||||||
|
* (200-400ns) and 1 as a long pulse (580ns-1us). Before sending the data reset
|
||||||
|
* period is required: at least 80us without pulses.
|
||||||
|
*
|
||||||
|
* The data send to LED is 24 bit RGB. These data are encoded as the long and
|
||||||
|
* short pulses.
|
||||||
|
*
|
||||||
|
* After data is sent, the PWM compare level is set to 0 to stop pulsing.
|
||||||
|
*
|
||||||
|
* For pulse generation with precise timing PWM implemented via TIM8 is used.
|
||||||
|
* To avoid any glitches when setting the CCR register, preloading is used,
|
||||||
|
* therefore sync with TIM4 is needed (to generate COM event on TIM update)
|
||||||
|
*
|
||||||
|
* DMA is used to set the CCR register to avoid need for interrupt after every
|
||||||
|
* bit is sent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include STM32_HAL_H
|
||||||
|
|
||||||
|
#define RESET_DATA_LEN 18 // >80us no pulse before sending data
|
||||||
|
#define DATA_LEN 25 // 24 RGB bits and a final zero
|
||||||
|
#define TIMER_PERIOD 832 // cca 200 KHz @ 180MHz
|
||||||
|
#define BIT_0_LEN 52 // 312ns
|
||||||
|
#define BIT_1_LEN 125 // 750ns
|
||||||
|
|
||||||
|
#if defined BOARDLOADER
|
||||||
|
#error Not implemented for boardloader!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined BOOTLOADER
|
||||||
|
__attribute__((section(".buf")))
|
||||||
|
#endif
|
||||||
|
uint32_t rgb_led_data[RESET_DATA_LEN + DATA_LEN] = {0};
|
||||||
|
|
||||||
|
static void rgb_led_set(uint32_t* start, uint8_t color) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
uint32_t bit_mask = (1 << (7 - i));
|
||||||
|
if (color & bit_mask) {
|
||||||
|
start[i] = BIT_1_LEN;
|
||||||
|
} else {
|
||||||
|
start[i] = BIT_0_LEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgb_led_set_color(uint32_t color) {
|
||||||
|
uint16_t red = (0xFF0000 & color) >> 16;
|
||||||
|
uint16_t green = (0xFF00 & color) >> 8;
|
||||||
|
uint16_t blue = (0xFF & color);
|
||||||
|
|
||||||
|
// wait for previous command to finish
|
||||||
|
while (DMA2_Stream1->CR & DMA_SxCR_EN)
|
||||||
|
;
|
||||||
|
|
||||||
|
rgb_led_set(&rgb_led_data[RESET_DATA_LEN + 0], green);
|
||||||
|
rgb_led_set(&rgb_led_data[RESET_DATA_LEN + 8], red);
|
||||||
|
rgb_led_set(&rgb_led_data[RESET_DATA_LEN + 16], blue);
|
||||||
|
rgb_led_data[RESET_DATA_LEN + DATA_LEN - 1] = 0;
|
||||||
|
|
||||||
|
DMA2->LIFCR |= 0xFC0;
|
||||||
|
DMA2_Stream1->M0AR = (uint32_t)rgb_led_data;
|
||||||
|
DMA2_Stream1->PAR = (uint32_t)&TIM8->CCR1;
|
||||||
|
DMA2_Stream1->NDTR = RESET_DATA_LEN + DATA_LEN;
|
||||||
|
DMA2_Stream1->CR |= DMA_SxCR_EN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgb_led_init(void) {
|
||||||
|
__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_TIM4_CLK_ENABLE();
|
||||||
|
TIM_HandleTypeDef TIM4_Handle;
|
||||||
|
TIM4_Handle.State = HAL_TIM_STATE_RESET;
|
||||||
|
TIM4_Handle.Instance = TIM4;
|
||||||
|
TIM4_Handle.Init.Period = TIMER_PERIOD;
|
||||||
|
TIM4_Handle.Init.Prescaler = 0;
|
||||||
|
TIM4_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||||
|
TIM4_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||||
|
TIM4_Handle.Init.RepetitionCounter = 0;
|
||||||
|
HAL_TIM_PWM_Init(&TIM4_Handle);
|
||||||
|
|
||||||
|
__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_NORMAL;
|
||||||
|
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->SMCR |= TIM_SMCR_SMS_2; // reset mode - sync timers
|
||||||
|
TIM8->SMCR |= TIM_SMCR_TS_1; // sync with TIM 4
|
||||||
|
|
||||||
|
TIM8->DIER |= TIM_DMA_UPDATE; // allow DMA request from update event
|
||||||
|
TIM8->CCR1 = 0;
|
||||||
|
|
||||||
|
// NVIC configuration for SDIO interrupts
|
||||||
|
HAL_TIM_Base_Start(&TIM4_Handle);
|
||||||
|
HAL_TIM_Base_Start(&TIM8_Handle);
|
||||||
|
HAL_TIM_PWM_Start(&TIM8_Handle, TIM_CHANNEL_1);
|
||||||
|
|
||||||
|
// turns off the LED
|
||||||
|
rgb_led_set_color(0x000000);
|
||||||
|
}
|
4
core/embed/trezorhal/rgb_led.h
Normal file
4
core/embed/trezorhal/rgb_led.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
void rgb_led_init(void);
|
||||||
|
|
||||||
|
void rgb_led_set_color(uint32_t color);
|
4
core/embed/unix/rgb_led.h
Normal file
4
core/embed/unix/rgb_led.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
void rgb_led_init(void);
|
||||||
|
|
||||||
|
void rgb_led_set_color(uint32_t color);
|
Loading…
Reference in New Issue
Block a user