diff --git a/bl/bl.h b/bl/bl.h index 33a90a5..27f5bcf 100644 --- a/bl/bl.h +++ b/bl/bl.h @@ -14,19 +14,28 @@ #include "jd_physical.h" #include "jd_control.h" -#define CPU_MHZ PLL_MHZ +#ifndef QUICK_LOG +#define QUICK_LOG 0 +#endif + +#define CPU_MHZ HSI_MHZ typedef void (*cb_t)(void); typedef struct ctx { uint8_t jd_state; - uint8_t uart_mode; - uint8_t tx_full, rx_full; uint8_t chunk_no; uint8_t bl_ad_queued; uint8_t id_counter; + uint8_t low_detected; + +#if QUICK_LOG == 1 + volatile uint32_t *log_reg; + uint32_t log_p0; + uint32_t log_p1; +#endif // these three fields are sent directly from here, so don't move them uint32_t session_id; @@ -36,12 +45,8 @@ typedef struct ctx { uint32_t randomseed; uint32_t service_class_bl; - uint8_t *uart_data; - uint32_t uart_bytesleft; - // timestamps uint32_t now; - uint32_t low_start; uint32_t tx_start_time; uint32_t led_off_time; uint32_t next_announce; @@ -55,24 +60,45 @@ typedef struct ctx { uint8_t pagedata[FLASH_PAGE_SIZE]; } ctx_t; +#if QUICK_LOG == 1 +#define LOG0_ON() *ctx->log_reg = ctx->log_p0 +#define LOG1_ON() *ctx->log_reg = ctx->log_p1 +#define LOG0_OFF() *ctx->log_reg = ctx->log_p0 << 16 +#define LOG1_OFF() *ctx->log_reg = ctx->log_p1 << 16 +#else +#define LOG0_ON() ((void)0) +#define LOG1_ON() ((void)0) +#define LOG0_OFF() ((void)0) +#define LOG1_OFF() ((void)0) +#endif +#define LOG0_PULSE() \ + do { \ + LOG0_ON(); \ + LOG0_OFF(); \ + } while (0) +#define LOG1_PULSE() \ + do { \ + LOG1_ON(); \ + LOG1_OFF(); \ + } while (0) + extern ctx_t ctx_; -void jd_process(ctx_t *ctx); +int jd_process(ctx_t *ctx); void jd_prep_send(ctx_t *ctx); void tim_init(void); uint32_t tim_get_micros(void); -#define UART_MODE_NONE 0 -#define UART_MODE_RX 1 -#define UART_MODE_TX 2 + void uart_init(ctx_t *ctx); -int uart_start_tx(ctx_t *ctx, const void *data, uint32_t numbytes); -void uart_start_rx(ctx_t *ctx, void *data, uint32_t maxbytes); -#define UART_END_TX 1 -#define UART_END_RX 2 -int uart_process(ctx_t *ctx); +int uart_tx(ctx_t *ctx, const void *data, uint32_t numbytes); +#define RX_LINE_BUSY 1 +#define RX_LINE_IDLE 2 +#define RX_RECEPTION_OK 3 +int uart_rx(ctx_t *ctx, void *data, uint32_t maxbytes); +void uart_post_rx(ctx_t *ctx); uint16_t crc16(const void *data, uint32_t size); diff --git a/bl/bljd.c b/bl/bljd.c index 2d924a3..888d318 100644 --- a/bl/bljd.c +++ b/bl/bljd.c @@ -71,53 +71,49 @@ void jd_prep_send(ctx_t *ctx) { ctx->tx_full = 1; } -void jd_process(ctx_t *ctx) { - uint32_t now = ctx->now; +int jd_process(ctx_t *ctx) { + int rx_status = uart_rx(ctx, &ctx->rxBuffer, sizeof(ctx->rxBuffer)); - if (ctx->uart_mode == UART_MODE_NONE) { - if (pin_get(UART_PIN)) { - if (!ctx->rx_full && ctx->low_start && 9 <= now - ctx->low_start && - now - ctx->low_start <= 50) { - ctx->rx_full = 1; - uart_start_rx(ctx, &ctx->rxBuffer, sizeof(ctx->rxBuffer)); - } else if (ctx->tx_full == 1 && !ctx->tx_start_time) { - ctx->tx_start_time = now + 40 + (random(ctx) & 127); - } else if (ctx->tx_start_time && ctx->tx_start_time <= now) { - ctx->tx_start_time = 0; - if (uart_start_tx(ctx, &ctx->txBuffer, JD_FRAME_SIZE(&ctx->txBuffer)) == 0) { - // sent OK - ctx->tx_full = 2; - } else { - // not sent because line was low - // next loop iteration will pick it up as RX - } - } - ctx->low_start = 0; - } else { - if (!ctx->low_start) - ctx->low_start = now; - ctx->tx_start_time = 0; + if (rx_status == RX_RECEPTION_OK) { + if (valid_frame(ctx, &ctx->rxBuffer)) { + LOG0_PULSE(); + ctx->rx_full = 1; } + LOG0_PULSE(); + uart_post_rx(ctx); + ctx->tx_start_time = 0; + return 1; + } - // only process frame when uart isn't busy - if (!ctx->tx_full && ctx->rx_full == 2) { - process_frame(ctx, &ctx->rxBuffer); - ctx->rx_full = 0; - } - } else { - switch (uart_process(ctx)) { - case UART_END_RX: - if (valid_frame(ctx, &ctx->rxBuffer)) - ctx->rx_full = 2; - else - ctx->rx_full = 0; - break; - case UART_END_TX: + if (rx_status == RX_LINE_BUSY) { + LOG0_PULSE(); + ctx->tx_start_time = 0; + return 1; + } + + if (ctx->tx_full == 1 && !ctx->tx_start_time) { + ctx->tx_start_time = ctx->now + 40 + (random(ctx) & 127); + } else if (ctx->tx_start_time && ctx->tx_start_time <= ctx->now) { + ctx->tx_start_time = 0; + if (uart_tx(ctx, &ctx->txBuffer, JD_FRAME_SIZE(&ctx->txBuffer)) == 0) { + // sent OK ctx->tx_full = 0; - break; + return 1; + } else { + // not sent because line was low + // next loop iteration will pick it up as RX + return 1; } } - identify(ctx); - bl_process(ctx); + // only process frame when uart isn't busy + if (!ctx->tx_full && ctx->rx_full) { + process_frame(ctx, &ctx->rxBuffer); + ctx->rx_full = 0; + return 1; + } else { + identify(ctx); + bl_process(ctx); + return 0; + } } diff --git a/bl/blmain.c b/bl/blmain.c index 998a663..29b6388 100644 --- a/bl/blmain.c +++ b/bl/blmain.c @@ -13,6 +13,10 @@ ctx_t ctx_; void led_init(void) { pin_setup_output(PIN_LED); pin_setup_output(PIN_LED_GND); +#if QUICK_LOG == 1 + pin_setup_output(PIN_X0); + pin_setup_output(PIN_X1); +#endif pin_set(PIN_LED_GND, 0); } @@ -45,7 +49,7 @@ uint32_t bl_adc_random_seed(void); int main(void) { __disable_irq(); - clk_setup_pll(); + // clk_setup_pll(); #if USART_IDX == 1 #ifdef STM32G0 @@ -110,7 +114,7 @@ int main(void) { bool app_valid = bl_fixup_app_handlers(ctx); -#if 1 +#if 0 if (app_valid) ctx->app_start_time = 512 * 1024; else @@ -122,9 +126,10 @@ int main(void) { while (1) { uint32_t now = ctx->now = tim_get_micros(); - // pin_pulse(PIN_LOG0, 1); + LOG1_PULSE(); - jd_process(ctx); + if (jd_process(ctx)) + continue; if (now >= ctx->next_announce && !ctx->tx_full) { memcpy(ctx->txBuffer.data, announce_data, sizeof(announce_data)); @@ -134,13 +139,14 @@ int main(void) { if (now >= ctx->app_start_time) start_app(); + if (ctx->led_off_time) { if (ctx->led_off_time < now) { led_set(0); ctx->led_off_time = 0; } } else { - led_set((now & 0xff) < ((now & 0x80000) ? 0x4 : 0xf)); + led_set((now & 0x3f) < ((now & 0x80000) ? 0x1 : 0x4)); } } } diff --git a/bl/bluart.c b/bl/bluart.c index 3989388..a408eb8 100644 --- a/bl/bluart.c +++ b/bl/bluart.c @@ -40,29 +40,7 @@ static void uartDoesntOwnPin(void) { LL_GPIO_SetPinMode(PIN_PORT, PIN_PIN, LL_GPIO_MODE_INPUT); } -void uart_init(ctx_t *ctx) { - LL_GPIO_SetPinPull(PIN_PORT, PIN_PIN, LL_GPIO_PULL_UP); - LL_GPIO_SetPinSpeed(PIN_PORT, PIN_PIN, LL_GPIO_SPEED_FREQ_HIGH); - uartDoesntOwnPin(); - - USARTx->CR1 = LL_USART_DATAWIDTH_8B | LL_USART_PARITY_NONE | LL_USART_OVERSAMPLING_16 | - LL_USART_DIRECTION_TX; - USARTx->BRR = CPU_MHZ; // ->1MHz - -#ifdef LL_USART_PRESCALER_DIV1 - LL_USART_SetPrescaler(USARTx, LL_USART_PRESCALER_DIV1); -#endif - - LL_USART_ConfigHalfDuplexMode(USARTx); -} - -void uart_disable(ctx_t *ctx) { - LL_USART_Disable(USARTx); - uartDoesntOwnPin(); - ctx->uart_mode = UART_MODE_NONE; -} - -void uart_start_rx(ctx_t *ctx, void *data, uint32_t maxbytes) { +static void rx_setup(void) { uartOwnsPin(); LL_USART_DisableDirectionTx(USARTx); LL_USART_EnableDirectionRx(USARTx); @@ -70,53 +48,92 @@ void uart_start_rx(ctx_t *ctx, void *data, uint32_t maxbytes) { LL_USART_Enable(USARTx); while (!(LL_USART_IsActiveFlag_REACK(USARTx))) ; - - ctx->uart_data = data; - ctx->uart_bytesleft = maxbytes; - ctx->rx_timeout = ctx->now + maxbytes * 15; - ctx->uart_mode = UART_MODE_RX; } -int uart_process(ctx_t *ctx) { +void uart_init(ctx_t *ctx) { +#if QUICK_LOG == 1 + ctx->log_reg = (volatile uint32_t *)&PORT(PIN_X0)->BSRR; + ctx->log_p0 = PIN(PIN_X0); + ctx->log_p1 = PIN(PIN_X1); +#endif + + LL_GPIO_SetPinPull(PIN_PORT, PIN_PIN, LL_GPIO_PULL_UP); + LL_GPIO_SetPinSpeed(PIN_PORT, PIN_PIN, LL_GPIO_SPEED_FREQ_HIGH); + uartDoesntOwnPin(); + + USARTx->CR1 = LL_USART_DATAWIDTH_8B | LL_USART_PARITY_NONE | LL_USART_OVERSAMPLING_8 | + LL_USART_DIRECTION_TX; + USARTx->BRR = CPU_MHZ * 2; // ->1MHz + +#ifdef LL_USART_PRESCALER_DIV1 + LL_USART_SetPrescaler(USARTx, LL_USART_PRESCALER_DIV1); +#endif + + LL_USART_ConfigHalfDuplexMode(USARTx); + + rx_setup(); +} + +void uart_disable(ctx_t *ctx) { + LL_USART_Disable(USARTx); + uartDoesntOwnPin(); +} + +int uart_rx(ctx_t *ctx, void *data, uint32_t maxbytes) { uint32_t isr = USARTx->ISR; - if (ctx->uart_mode == UART_MODE_RX) { - if (isr & USART_ISR_FE || ctx->now > ctx->rx_timeout) { - uart_disable(ctx); - return UART_END_RX; - } else if (isr & USART_ISR_RXNE) { - uint8_t c = USARTx->RDR; - if (ctx->uart_bytesleft) { - ctx->uart_bytesleft--; - *ctx->uart_data++ = c; - } - } - } else if (ctx->uart_mode == UART_MODE_TX) { - if (isr & USART_ISR_TXE) { - if (ctx->uart_bytesleft) { - ctx->uart_bytesleft--; - USARTx->TDR = *ctx->uart_data++; - } else { - if (!LL_USART_IsActiveFlag_TC(USARTx)) - return 0; - LL_USART_Disable(USARTx); - LL_GPIO_SetPinMode(PIN_PORT, PIN_PIN, LL_GPIO_MODE_OUTPUT); - LL_GPIO_ResetOutputPin(PIN_PORT, PIN_PIN); - target_wait_us(12); - LL_GPIO_SetOutputPin(PIN_PORT, PIN_PIN); - uart_disable(ctx); - return UART_END_TX; - } + + if (ctx->low_detected || !(isr & USART_ISR_FE)) { + if (isr & USART_ISR_BUSY) + return RX_LINE_BUSY; + return RX_LINE_IDLE; + } + + ctx->low_detected = 0; + + // wait for BUSY to be cleared - ie the low pulse has ended + while (isr & USART_ISR_BUSY) + isr = USARTx->ISR; + + uart_post_rx(ctx); // clear errors + + uint8_t *dp = data; + int32_t delaycnt = -10 * CPU_MHZ; // allow a bit more delay at the start + LOG0_PULSE(); + while (maxbytes > 0) { + isr = USARTx->ISR; + if (isr & USART_ISR_RXNE) { + *dp++ = USARTx->RDR; + maxbytes--; + delaycnt = 0; + } else if (isr & USART_ISR_FE || delaycnt > 4 * CPU_MHZ) { + break; + } else { + delaycnt++; } } - return 0; + LOG0_PULSE(); + + return RX_RECEPTION_OK; } -int uart_start_tx(ctx_t *ctx, const void *data, uint32_t numbytes) { +void uart_post_rx(ctx_t *ctx) { + (void)USARTx->RDR; + USARTx->ICR = USART_ISR_FE | USART_ISR_NE | USART_ISR_ORE; + (void)USARTx->RDR; +} + +int uart_tx(ctx_t *ctx, const void *data, uint32_t numbytes) { + LL_USART_Disable(USARTx); + uartDoesntOwnPin(); + LL_GPIO_ResetOutputPin(PIN_PORT, PIN_PIN); gpio_probe_and_set(PIN_PORT, PIN_PIN, PIN_MODER | PIN_PORT->MODER); if (!(PIN_PORT->MODER & PIN_MODER)) { + ctx->low_detected = 1; + rx_setup(); return -1; } + target_wait_us(11); LL_GPIO_SetOutputPin(PIN_PORT, PIN_PIN); @@ -128,11 +145,26 @@ int uart_start_tx(ctx_t *ctx, const void *data, uint32_t numbytes) { while (!(LL_USART_IsActiveFlag_TEACK(USARTx))) ; - ctx->uart_data = (void *)data; - ctx->uart_bytesleft = numbytes; - ctx->uart_mode = UART_MODE_TX; - + const uint8_t *sp = data; target_wait_us(40); + while (numbytes > 0) { + uint32_t isr = USARTx->ISR; + if (isr & USART_ISR_TXE) { + numbytes--; + USARTx->TDR = *sp++; + } + } + + while (!LL_USART_IsActiveFlag_TC(USARTx)) + ; + + LL_USART_Disable(USARTx); + LL_GPIO_SetPinMode(PIN_PORT, PIN_PIN, LL_GPIO_MODE_OUTPUT); + LL_GPIO_ResetOutputPin(PIN_PORT, PIN_PIN); + target_wait_us(12); + LL_GPIO_SetOutputPin(PIN_PORT, PIN_PIN); + rx_setup(); + return 0; }