diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c index 81754ac15f43f..2e5ce942ba206 100644 --- a/drivers/dht/dht.c +++ b/drivers/dht/dht.c @@ -1,3 +1,4 @@ +#ifdef MICROPY_HW_ENABLE_DHT /* * This file is part of the MicroPython project, http://micropython.org/ * @@ -92,3 +93,5 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) { mp_raise_OSError(MP_ETIMEDOUT); } MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto); + +#endif diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c index 195a24334b69f..8c95bde2aff0c 100644 --- a/extmod/moduhashlib.c +++ b/extmod/moduhashlib.c @@ -98,7 +98,9 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, 32); - mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf); + mbedtls_sha256_context tmp_ctx; + memcpy(&tmp_ctx, self->state, sizeof(tmp_ctx)); + mbedtls_sha256_finish_ret(&tmp_ctx, (unsigned char *)vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } @@ -129,7 +131,9 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); vstr_t vstr; vstr_init_len(&vstr, SHA256_BLOCK_SIZE); - sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf); + CRYAL_SHA256_CTX tmp_ctx; + memcpy(&tmp_ctx, self->state, sizeof(tmp_ctx)); + sha256_final(&tmp_ctx, (byte *)vstr.buf); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); } #endif diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 95b7ad9944116..0166008ae9f34 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -379,6 +379,9 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) { uint8_t working_buf[FF_MAX_SS]; res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); + if (res == FR_MKFS_ABORTED) { // Probably doesn't support FAT16 + res = f_mkfs(&self->fatfs, FM_FAT32, 0, working_buf, sizeof(working_buf)); + } } if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 719afe28fe87f..d9d45c8a72b69 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -37,6 +37,7 @@ #include #include #include +#include typedef struct _mp_obj_vfs_posix_t { mp_obj_base_t base; diff --git a/ports/.gitignore b/ports/.gitignore new file mode 100644 index 0000000000000..059c3f194d12a --- /dev/null +++ b/ports/.gitignore @@ -0,0 +1,5 @@ +# this file only useful for Coldcard project +stm32/boards/COLDCARD +unix/coldcard-mpy +unix/unix_random.P + diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c index c92090699108e..69c5f25082b04 100644 --- a/ports/stm32/modpyb.c +++ b/ports/stm32/modpyb.c @@ -30,7 +30,9 @@ #include "py/runtime.h" #include "py/mphal.h" #include "lib/utils/pyexec.h" +#if MICROPY_HW_ENABLE_DHT #include "drivers/dht/dht.h" +#endif #include "stm32_it.h" #include "irq.h" #include "led.h" @@ -189,8 +191,10 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, #endif +#if MICROPY_HW_ENABLE_DHT // This function is not intended to be public and may be moved elsewhere { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, +#endif { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) }, diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 948897b215717..12a026deaa39f 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -162,6 +162,11 @@ #define MICROPY_HW_UART_IS_RESERVED(uart_id) (false) #endif +// Defines which UART ports are to be half-duplex +#ifndef MICROPY_HW_UARTn_IS_HALF_DUPLEX +#define MICROPY_HW_UARTn_IS_HALF_DUPLEX(n) (0) +#endif + /*****************************************************************************/ // General configuration @@ -399,3 +404,9 @@ #endif #define MICROPY_HW_USES_BOOTLOADER (MICROPY_HW_VTOR != 0x08000000) + +// drivers/dht ... a specific enviro sensor of some sort +#ifndef MICROPY_HW_ENABLE_DHT +#define MICROPY_HW_ENABLE_DHT (1) +#endif + diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index b255ee82ca9be..d2e92035dc019 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -730,25 +730,32 @@ STATIC mp_obj_t sd_info(mp_obj_t self) { uint32_t card_type; uint32_t log_block_nbr; uint32_t log_block_size; + const uint8_t *CSD = NULL, *CID = NULL; #if MICROPY_HW_ENABLE_MMCARD if (pyb_sdmmc_flags & PYB_SDMMC_FLAG_MMC) { card_type = sdmmc_handle.mmc.MmcCard.CardType; log_block_nbr = sdmmc_handle.mmc.MmcCard.LogBlockNbr; log_block_size = sdmmc_handle.mmc.MmcCard.LogBlockSize; + CSD = sdmmc_handle.mmc.MmcCard.CSD; + CID = sdmmc_handle.mmc.MmcCard.CID; } else #endif { card_type = sdmmc_handle.sd.SdCard.CardType; log_block_nbr = sdmmc_handle.sd.SdCard.LogBlockNbr; log_block_size = sdmmc_handle.sd.SdCard.LogBlockSize; + CSD = sdmmc_handle.sd.SdCard.CSD; + CID = sdmmc_handle.sd.SdCard.CID; } - // cardinfo.SD_csd and cardinfo.SD_cid have lots of info but we don't use them - mp_obj_t tuple[3] = { + // cardinfo.SD_csd and cardinfo.SD_cid have lots of info so let's share them + mp_obj_t tuple[5] = { mp_obj_new_int_from_ull((uint64_t)log_block_nbr * (uint64_t)log_block_size), mp_obj_new_int_from_uint(log_block_size), mp_obj_new_int(card_type), + mp_obj_new_bytes(CSD, 16), + mp_obj_new_bytes(CID, 16), }; - return mp_obj_new_tuple(3, tuple); + return mp_obj_new_tuple(5, tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(sd_info_obj, sd_info); diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index 2160e0ac994c6..e4f0376ad2919 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -163,7 +163,7 @@ void __fatal_error(const char *msg); * * Timers run from APBx if APBx_PRESC=1, else 2x APBx */ -void SystemClock_Config(void) { +MP_WEAK void SystemClock_Config(void) { #if defined(STM32F7) // The DFU bootloader changes the clocksource register from its default power // on reset value, so we set it back here, so the clocksources are the same diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index d40a883c52b84..25e3f2b7eb77f 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -464,7 +464,13 @@ bool uart_init(pyb_uart_obj_t *uart_obj, huart.Init.Mode = UART_MODE_TX_RX; huart.Init.HwFlowCtl = flow; huart.Init.OverSampling = UART_OVERSAMPLING_16; - HAL_UART_Init(&huart); + if(MICROPY_HW_UARTn_IS_HALF_DUPLEX(uart_obj->uart_id)) { + // init in half-duplex mode + HAL_HalfDuplex_Init(&uart_obj->uart); + } else { + // init UARTx + HAL_UART_Init(&uart_obj->uart); + } // Disable all individual UART IRQs, but enable the global handler uart_obj->uartx->CR1 &= ~USART_CR1_IE_ALL; @@ -925,10 +931,209 @@ void uart_irq_handler(mp_uint_t uart_id) { } } } +<<<<<<< HEAD +} + +/******************************************************************************/ +/* MicroPython bindings */ + +STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pyb_uart_obj_t *self = self_in; + if (!self->is_enabled) { + mp_printf(print, "UART(%u)", self->uart_id); + } else { + mp_int_t bits; + switch (self->uart.Init.WordLength) { + #ifdef UART_WORDLENGTH_7B + case UART_WORDLENGTH_7B: bits = 7; break; + #endif + case UART_WORDLENGTH_8B: bits = 8; break; + case UART_WORDLENGTH_9B: default: bits = 9; break; + } + if (self->uart.Init.Parity != UART_PARITY_NONE) { + bits -= 1; + } + mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=", + self->uart_id, self->uart.Init.BaudRate, bits); + if (self->uart.Init.Parity == UART_PARITY_NONE) { + mp_print_str(print, "None"); + } else { + mp_printf(print, "%u", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); + } + if (self->uart.Init.HwFlowCtl) { + mp_printf(print, ", flow="); + if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) { + mp_printf(print, "RTS%s", self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS ? "|" : ""); + } + if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) { + mp_printf(print, "CTS"); + } + } + if(MICROPY_HW_UARTn_IS_HALF_DUPLEX(self->uart_id)) { + mp_printf(print, ", half=1"); + } + mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u)", + self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2, + self->timeout, self->timeout_char, + self->read_buf_len == 0 ? 0 : self->read_buf_len - 1); // -1 to adjust for usable length of buffer + } +} + +/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, flow=0, read_buf_len=64) +/// +/// Initialise the UART bus with the given parameters: +/// +/// - `baudrate` is the clock rate. +/// - `bits` is the number of bits per byte, 7, 8 or 9. +/// - `parity` is the parity, `None`, 0 (even) or 1 (odd). +/// - `stop` is the number of stop bits, 1 or 2. +/// - `timeout` is the timeout in milliseconds to wait for the first character. +/// - `timeout_char` is the timeout in milliseconds to wait between characters. +/// - `flow` is RTS | CTS where RTS == 256, CTS == 512 +/// - `read_buf_len` is the character length of the read buffer (0 to disable). +STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} }, + { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_HWCONTROL_NONE} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, + { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, + }; + + // parse args + struct { + mp_arg_val_t baudrate, bits, parity, stop, flow, timeout, timeout_char, read_buf_len; + } args; + mp_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); + + // set the UART configuration values + memset(&self->uart, 0, sizeof(self->uart)); + UART_InitTypeDef *init = &self->uart.Init; + + // baudrate + init->BaudRate = args.baudrate.u_int; + + // parity + mp_int_t bits = args.bits.u_int; + if (args.parity.u_obj == mp_const_none) { + init->Parity = UART_PARITY_NONE; + } else { + mp_int_t parity = mp_obj_get_int(args.parity.u_obj); + init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN; + bits += 1; // STs convention has bits including parity + } + + // number of bits + if (bits == 8) { + init->WordLength = UART_WORDLENGTH_8B; + } else if (bits == 9) { + init->WordLength = UART_WORDLENGTH_9B; + #ifdef UART_WORDLENGTH_7B + } else if (bits == 7) { + init->WordLength = UART_WORDLENGTH_7B; + #endif + } else { + mp_raise_ValueError("unsupported combination of bits and parity"); + } + + // stop bits + switch (args.stop.u_int) { + case 1: init->StopBits = UART_STOPBITS_1; break; + default: init->StopBits = UART_STOPBITS_2; break; + } + + // flow control + init->HwFlowCtl = args.flow.u_int; + + // extra config (not yet configurable) + init->Mode = UART_MODE_TX_RX; + init->OverSampling = UART_OVERSAMPLING_16; + + // init UART (if it fails, it's because the port doesn't exist) + if (!uart_init2(self)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) doesn't exist", self->uart_id)); + } + + // set timeout + self->timeout = args.timeout.u_int; + + // set timeout_char + // make sure it is at least as long as a whole character (13 bits to be safe) + // minimum value is 2ms because sys-tick has a resolution of only 1ms + self->timeout_char = args.timeout_char.u_int; + uint32_t min_timeout_char = 13000 / init->BaudRate + 2; + if (self->timeout_char < min_timeout_char) { + self->timeout_char = min_timeout_char; + } + + // setup the read buffer + m_del(byte, self->read_buf, self->read_buf_len << self->char_width); + if (init->WordLength == UART_WORDLENGTH_9B && init->Parity == UART_PARITY_NONE) { + self->char_mask = 0x1ff; + self->char_width = CHAR_WIDTH_9BIT; + } else { + if (init->WordLength == UART_WORDLENGTH_9B || init->Parity == UART_PARITY_NONE) { + self->char_mask = 0xff; + } else { + self->char_mask = 0x7f; + } + self->char_width = CHAR_WIDTH_8BIT; + } + self->read_buf_head = 0; + self->read_buf_tail = 0; + if (args.read_buf_len.u_int <= 0) { + // no read buffer + self->read_buf_len = 0; + self->read_buf = NULL; + HAL_NVIC_DisableIRQ(self->irqn); + __HAL_UART_DISABLE_IT(&self->uart, UART_IT_RXNE); + } else { + // read buffer using interrupts + self->read_buf_len = args.read_buf_len.u_int + 1; // +1 to adjust for usable length of buffer + self->read_buf = m_new(byte, self->read_buf_len << self->char_width); + __HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE); + NVIC_SetPriority(IRQn_NONNEG(self->irqn), IRQ_PRI_UART); + HAL_NVIC_EnableIRQ(self->irqn); + } + + // compute actual baudrate that was configured + // (this formula assumes UART_OVERSAMPLING_16) + uint32_t actual_baudrate = 0; + #if defined(STM32F0) + actual_baudrate = HAL_RCC_GetPCLK1Freq(); + #elif defined(STM32F7) || defined(STM32H7) + UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED; + UART_GETCLOCKSOURCE(&self->uart, clocksource); + switch (clocksource) { + #if defined(STM32H7) + case UART_CLOCKSOURCE_D2PCLK1: actual_baudrate = HAL_RCC_GetPCLK1Freq(); break; + case UART_CLOCKSOURCE_D3PCLK1: actual_baudrate = HAL_RCC_GetPCLK1Freq(); break; + case UART_CLOCKSOURCE_D2PCLK2: actual_baudrate = HAL_RCC_GetPCLK2Freq(); break; + #else + case UART_CLOCKSOURCE_PCLK1: actual_baudrate = HAL_RCC_GetPCLK1Freq(); break; + case UART_CLOCKSOURCE_PCLK2: actual_baudrate = HAL_RCC_GetPCLK2Freq(); break; + case UART_CLOCKSOURCE_SYSCLK: actual_baudrate = HAL_RCC_GetSysClockFreq(); break; + #endif + #if defined(STM32H7) + case UART_CLOCKSOURCE_CSI: actual_baudrate = CSI_VALUE; break; + #endif + case UART_CLOCKSOURCE_HSI: actual_baudrate = HSI_VALUE; break; + case UART_CLOCKSOURCE_LSE: actual_baudrate = LSE_VALUE; break; + #if defined(STM32H7) + case UART_CLOCKSOURCE_PLL2: + case UART_CLOCKSOURCE_PLL3: + #endif + case UART_CLOCKSOURCE_UNDEFINED: break; +======= // If RXNE is clear but ORE set then clear the ORE flag (it's tied to RXNE IRQ) #if defined(STM32F4) else if (self->uartx->SR & USART_SR_ORE) { (void)self->uartx->DR; +>>>>>>> upstream/master } #else else if (self->uartx->ISR & USART_ISR_ORE) { diff --git a/tests/extmod/uhashlib_sha256.py b/tests/extmod/uhashlib_sha256.py index 2e6df7df13202..60c3b54ef0787 100644 --- a/tests/extmod/uhashlib_sha256.py +++ b/tests/extmod/uhashlib_sha256.py @@ -26,13 +26,13 @@ # 56 bytes is a boundary case in the algorithm print(hashlib.sha256(b"\xff" * 56).digest()) -# TODO: running .digest() several times in row is not supported() -# h = hashlib.sha256(b'123') -# print(h.digest()) -# print(h.digest()) - -# TODO: partial digests are not supported -# h = hashlib.sha256(b'123') -# print(h.digest()) -# h.update(b'456') -# print(h.digest()) +# running .digest() several times in row is now supported +h = hashlib.sha256(b'123') +print(h.digest()) +print(h.digest()) + +# partial digests are supported +h = hashlib.sha256(b'123') +print(h.digest()) +h.update(b'456') +print(h.digest()) diff --git a/tools/pydfu.py b/tools/pydfu.py index 42b4fa2da6feb..2287aadd888f8 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -79,6 +79,7 @@ # USB DFU interface __DFU_INTERFACE = 0 +import inspect # Python 3 deprecated getargspec in favour of getfullargspec, but # Python 2 doesn't have the latter, so detect which one to use getargspec = getattr(inspect, "getfullargspec", inspect.getargspec)