int main(void) { init(1); printf("\n\nFirmware info - git: " GIT_VERSION ", built: " __DATE__ " " __TIME__ "\n"); printf("--- SWIFT BINARY PROTOCOL RX STRESS TEST ---\n"); static sbp_msg_callbacks_node_t callback_node; sbp_register_cbk(0x22, &callback, &callback_node); for (u8 i=0; i<30; i++) { guard_below[i] = 0; guard_above[i] = 0; } while(1) { /* Check the guards for buffer over/underrun. */ for (u8 i=0; i<30; i++) { if (guard_below[i] != 0) screaming_death("Detected buffer underrun in guard area\n"); if (guard_above[i] != 0) screaming_death("Detected buffer overrun in guard area\n"); } sbp_process_messages(); //for (u32 i = 0; i < 1000; i++) // __asm__("nop"); } while (1); return 0; }
int main(void) { for (u32 i = 0; i < 600000; i++) __asm__("nop"); led_setup(); rcc_clock_setup_hse_3v3(&hse_16_368MHz_in_65_472MHz_out_3v3); debug_setup(); timer_setup(); // Debug pins (CC1111 TX/RX) RCC_AHB1ENR |= RCC_AHB1ENR_IOPCEN; gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO10|GPIO11); gpio_clear(GPIOC, GPIO10|GPIO11); printf("\n\nFirmware info - git: " GIT_VERSION ", built: " __DATE__ " " __TIME__ "\n"); printf("--- DEBUG TEST ---\n"); u32 len; for (u8 i=0; i<30; i++) { guard_below[i] = 0; guard_above[i] = 0; } for (u32 i=0; i<256; i++) buff_out[i] = (u8)i; while(1) { /* Random transmit length. */ len = (u32)rand() % 256; while(debug_send_msg(0x22, len, buff_out)); /* Check the guards for buffer over/underrun. */ for (u8 i=0; i<30; i++) { if (guard_below[i] != 0) screaming_death(); if (guard_above[i] != 0) screaming_death(); } /* Introduce some timing jitter. */ u32 jitter_delay = ((u32)rand() % 20000); for (u32 i = 0; i < jitter_delay; i++) /*for (u32 i = 0; i < 1000; i++)*/ __asm__("nop"); } while (1); return 0; }
int main(void) { for (u32 i = 0; i < 600000; i++) __asm__("nop"); led_setup(); rcc_clock_setup_hse_3v3(&hse_16_368MHz_in_65_472MHz_out_3v3); usart_setup_common(); usart_tx_dma_setup(); /*printf("\n\nFirmware info - git: " GIT_VERSION ", built: " __DATE__ " " __TIME__ "\n");*/ /*printf("--- USART DMA TEST ---\n");*/ #define MAX_TX ((u32)(USART_TX_BUFFER_LEN*1.2)) u8 guard_below[30]; u8 buff_out[MAX_TX]; u8 guard_above[30]; u32 len; for (u8 i=0; i<30; i++) { guard_below[i] = 0; guard_above[i] = 0; } for (u32 i=0; i<MAX_TX; i++) buff_out[i] = (u8)i; while(1) { /* Random transmit length. */ len = (u32)rand() % MAX_TX; while (len) len -= usart_write_dma(buff_out, len); /* Check the guards for buffer over/underrun. */ for (u8 i=0; i<30; i++) { if (guard_below[i] != 0) screaming_death(); if (guard_above[i] != 0) screaming_death(); } /* Introduce some timing jitter. */ for (u32 i = 0; i < ((u32)rand() % 10000); i++) __asm__("nop"); } while (1); return 0; }
/* Called by fault handlers in error_asm.s */ void fault_handler_screaming_death(const char *msg_str, u32 lr) { char msg[128]; extern int fallback_sprintf(char *str, const char *fmt, ...); fallback_sprintf(msg, "%s lr=%08X", msg_str, (unsigned int)lr); screaming_death(msg); }
/** _exit(2) syscall handler. Called by (at least) abort() and exit(). * Calls screaming_death() to repeatedly print an ERROR until WDT reset. */ void _exit(int status) { (void)status; /* TODO: Perhaps print a backtrace; let's see if this ever actually occurs before implementing that. */ screaming_death("abort() or exit() was called"); }
/** USART TX DMA interrupt service routine. * Should be called from the relevant DMA stream ISR. * \param s The USART DMA state structure. */ void usart_tx_dma_isr(usart_tx_dma_state* s) { if (dma_get_interrupt_flag(s->dma, s->stream, DMA_TEIF | DMA_DMEIF)) /* TODO: Handle error interrupts! */ screaming_death("DMA TX error interrupt"); if (dma_get_interrupt_flag(s->dma, s->stream, DMA_TCIF)) { /* Interrupt is Transmit Complete. */ /* Clear the DMA transmit complete and half complete interrupt flags. */ dma_clear_interrupt_flags(s->dma, s->stream, DMA_HTIF | DMA_TCIF); /* Now that the transfer has finished we can increment the read index. */ s->rd = (s->rd + s->xfer_len) % USART_TX_BUFFER_LEN; if (s->wr != s->rd) /* Buffer not empty. */ dma_schedule(s); } if (dma_get_interrupt_flag(s->dma, s->stream, DMA_FEIF)) /* Clear FIFO error flag */ dma_clear_interrupt_flags(s->dma, s->stream, DMA_HTIF | DMA_FEIF); }
/** Helper function that schedules a new transfer with the DMA controller if * needed. * \param s The USART DMA state structure. * */ static void dma_schedule(usart_tx_dma_state* s) { /* TODO: We shouldn't have to check for this now that we are called * atomically but leaving it in for now just in case. */ if (DMA_SCR(s->dma, s->stream) & DMA_SxCR_EN) screaming_death("DMA TX scheduled while DMA channel running"); DMA_SM0AR(s->dma, s->stream) = &(s->buff[s->rd]); /* Save the transfer length so we can increment the read index after the * transfer is finished. */ if (s->rd < s->wr) /* DMA up until write pointer. */ s->xfer_len = s->wr - s->rd; else /* DMA up until the end of the buffer. */ s->xfer_len = USART_TX_BUFFER_LEN - s->rd; /* Set the number of datas in the DMA controller. */ DMA_SNDTR(s->dma, s->stream) = s->xfer_len; /* Clear USART_TC flag */ USART_SR(s->usart) &= ~USART_SR_TC; /* Enable DMA stream to start transfer. */ DMA_SCR(s->dma, s->stream) |= DMA_SxCR_EN; }
int main(void) { for (u32 i = 0; i < 600000; i++) __asm__("nop"); led_setup(); rcc_clock_setup_hse_3v3(&hse_16_368MHz_in_65_472MHz_out_3v3); debug_setup(); timer_setup(); // Debug pins (CC1111 TX/RX) RCC_AHB1ENR |= RCC_AHB1ENR_IOPCEN; gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO10|GPIO11); gpio_clear(GPIOC, GPIO10|GPIO11); printf("\n\nFirmware info - git: " GIT_VERSION ", built: " __DATE__ " " __TIME__ "\n"); printf("--- DEBUG RX STRESS TEST ---\n"); static msg_callbacks_node_t callback_node; debug_register_callback(0x22, &callback, &callback_node); for (u8 i=0; i<30; i++) { guard_below[i] = 0; guard_above[i] = 0; } while(1) { /* Check the guards for buffer over/underrun. */ for (u8 i=0; i<30; i++) { if (guard_below[i] != 0) screaming_death(); if (guard_above[i] != 0) screaming_death(); } debug_process_messages(); //for (u32 i = 0; i < 1000; i++) // __asm__("nop"); } while (1); return 0; }
static void usart_rx_dma_isr(struct usart_rx_dma_state* s, u32 flags) { if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) screaming_death("USART RX DMA error interrupt"); chSysLockFromISR(); /* Increment our write wrap counter. */ s->wr_wraps++; chBSemSignalI(&s->ready); chSysUnlockFromISR(); }
void callback(u16 sender_id, u8 len, u8 msg[], void* context) { (void)sender_id; (void)len; (void) context; // Check this shit out ok_packets++; ok_bytes += 25; for (u8 i=0; i<22; i++) if (msg[i] != i) screaming_death("Test packet not received correctly"); }
/** DMA 2 Stream 3 Interrupt Service Routine. (SPI1_TX) */ void dma2_stream3_isr(void) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); if (dma_get_interrupt_flag(DMA2, 3, DMA_TEIF | DMA_DMEIF)) screaming_death("DMA SPI1_TX error interrupt"); chSysUnlockFromIsr(); CH_IRQ_EPILOGUE(); }
static void usart_tx_dma_isr(struct usart_tx_dma_state* s, u32 flags) { if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) screaming_death("USART TX DMA error interrupt"); osalSysLockFromISR(); /* Now that the transfer has finished we can increment the read index. */ s->rd = (s->rd + s->xfer_len) % USART_TX_BUFFER_LEN; if (s->wr != s->rd) /* Buffer not empty. */ dma_schedule(s); else s->busy = false; osalSysUnlockFromISR(); }
/** DMA 2 Stream 0 Interrupt Service Routine. (SPI1_RX) */ void dma2_stream0_isr(void) { CH_IRQ_PROLOGUE(); chSysLockFromIsr(); if (dma_get_interrupt_flag(DMA2, 0, DMA_TEIF | DMA_DMEIF)) screaming_death("DMA SPI1_RX error interrupt"); /* Disable both receive and transmit streams */ dma_clear_interrupt_flags(DMA2, 3, DMA_TCIF | DMA_HTIF); dma_clear_interrupt_flags(DMA2, 0, DMA_TCIF | DMA_HTIF); /* Signal the semaphore to wake up blocking spi1_xfer_dma */ chBSemSignalI(&spi_dma_sem); chSysUnlockFromIsr(); CH_IRQ_EPILOGUE(); }
/** Returns a lower bound on the number of bytes in the DMA receive buffer. * Also checks for buffer overrun conditions. * \param s The USART DMA state structure. */ u32 usart_n_read_dma(usart_rx_dma_state* s) { s32 n_read = s->rd_wraps * USART_RX_BUFFER_LEN + s->rd; s32 n_written = (s->wr_wraps + 1) * USART_RX_BUFFER_LEN - \ DMA_SNDTR(s->dma, s->stream); s32 n_available = n_written - n_read; if (n_available < 0) /* This strange and rare case occurs when NDTR has rolled over but the flag * hasn't been raised yet and thus n_wraps hasn't been incremented in the * ISR. Simply return 0 this time and the next time this function is called * (or at some point) the interrupt will have been triggered and the number * of bytes available in the buffer will be a sane amount. */ n_available = 0; else if (n_available > USART_RX_BUFFER_LEN) /* If greater than a whole buffer then we have had an overflow. */ screaming_death("DMA RX buffer overrun"); return n_available; }
/** USART RX DMA interrupt service routine. * Should be called from the relevant DMA stream ISR. * \param s The USART DMA state structure. */ void usart_rx_dma_isr(usart_rx_dma_state* s) { if (dma_get_interrupt_flag(s->dma, s->stream, DMA_TEIF | DMA_DMEIF | DMA_FEIF)) /* TODO: Handle error interrupts! */ screaming_death("USART RX DMA error interrupt"); if (dma_get_interrupt_flag(s->dma, s->stream, DMA_HTIF | DMA_TCIF)) { /* Interrupt is Transmit Complete. We are in circular buffer mode so this * probably means we just wrapped the buffer. */ /* Clear the DMA transmit complete and half complete interrupt flags. */ dma_clear_interrupt_flags(s->dma, s->stream, DMA_HTIF | DMA_TCIF); /* Increment our write wrap counter. */ s->wr_wraps++; } /* Note: When DMA is re-enabled after bootloader it appears ISR can get * called without any of the bits of DMA_LISR being high */ }