Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Some changes to debug/usart_tx for concurrency. Mutexes don't work fo…

…r us as we don't have a scheduler. Change debug_send_message to let the caller know if it can't write the message right now.
  • Loading branch information...
commit bdc5f5073e67ab0182faf10930284ccdf90fe048 1 parent d0fc399
@fnoble fnoble authored
Showing with 30 additions and 38 deletions.
  1. +14 −14 src/debug.c
  2. +1 −1  src/debug.h
  3. +1 −0  src/hw/usart.h
  4. +14 −23 src/hw/usart_tx.c
View
28 src/debug.c
@@ -17,8 +17,8 @@
#include <stdio.h>
#include <errno.h>
-#include <libopencm3/cm3/sync.h>
+#include "error.h"
#include "debug.h"
#include "hw/m25_flash.h"
#include "hw/leds.h"
@@ -49,25 +49,25 @@ void debug_setup()
/*setvbuf(stdout, NULL, _IONBF, 0);*/
}
-void debug_send_msg(u8 msg_type, u8 len, u8 buff[])
+u32 debug_send_msg(u8 msg_type, u8 len, u8 buff[])
{
- u8 n;
- static mutex_t m = MUTEX_UNLOCKED;
+ /* Global interrupt disable to avoid concurrency/reentrance problems. */
+ __asm__("CPSID i;");
+
+ if (usart_tx_n_free() < (u32)len+4) {
+ // Not enough space in the TX buffer for the message (including header)
+ __asm__("CPSIE i;"); // Re-enable interrupts
+ return 1; // Discard the message and return an error
+ }
- /* Use mutex to make sure the header and the body of the message are written
- * atomically together. */
- mutex_lock(&m);
msg_header[2] = msg_type;
msg_header[3] = len;
- n = 0;
- while (n < 4)
- n += usart_write_dma(&msg_header[n], 4 - n);
+ if (4 != usart_write_dma(msg_header, 4)) speaking_death("D_S_M: U_W_D failed (1)");
+ if (len != usart_write_dma(buff, len)) speaking_death("D_S_M: U_W_D failed (2)");
- n = 0;
- while (n < len)
- n += usart_write_dma(&buff[n], len - n);
- mutex_unlock(&m);
+ __asm__("CPSIE i;"); // Re-enable interrupts
+ return 0; // Successfully written to buffer.
}
/** Register a callback for a message type.
View
2  src/debug.h
@@ -39,7 +39,7 @@ typedef struct msg_callbacks_node {
} msg_callbacks_node_t;
void debug_setup();
-void debug_send_msg(u8 msg_type, u8 len, u8 buff[]);
+u32 debug_send_msg(u8 msg_type, u8 len, u8 buff[]);
void debug_register_callback(u8 msg_type, msg_callback_t cb, msg_callbacks_node_t* node);
msg_callback_t debug_find_callback(u8 msg_id);
void debug_process_messages();
View
1  src/hw/usart.h
@@ -27,6 +27,7 @@ void usart_setup_common(void);
void usart_tx_dma_setup(void);
void usart_rx_dma_setup(void);
+u32 usart_tx_n_free(void);
u32 usart_write_dma(u8 data[], u32 n);
u32 usart_n_read_dma();
View
37 src/hw/usart_tx.c
@@ -20,7 +20,6 @@
#include <libopencm3/stm32/f2/gpio.h>
#include <libopencm3/stm32/f2/rcc.h>
#include <libopencm3/stm32/nvic.h>
-#include <libopencm3/cm3/sync.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/f2/dma.h>
@@ -89,32 +88,28 @@ void usart_tx_dma_setup(void) {
/** Disable the USART TX DMA interrupt. Used to ensure that operations on the
* TX buffer happen "atomically". */
-static void usart_tx_di(void) {
- /* TODO: Change this so it doesn't just globally disable interrupts. */
- nvic_disable_irq(NVIC_DMA2_STREAM7_IRQ);
-}
+/*static void usart_tx_di(void) {*/
+ /*[> TODO: Change this so it doesn't just globally disable interrupts. <]*/
+ /*nvic_disable_irq(NVIC_DMA2_STREAM7_IRQ);*/
+/*}*/
/** Enable the USART TX DMA interrupt. */
-static void usart_tx_ei(void) {
- nvic_enable_irq(NVIC_DMA2_STREAM7_IRQ);
-}
+/*static void usart_tx_ei(void) {*/
+ /*nvic_enable_irq(NVIC_DMA2_STREAM7_IRQ);*/
+/*}*/
-/** Calculate the number of bytes currently in the TX buffer waiting to be
- * written out.
+/** Calculate the space left in the TX buffer.
*
- * \return The number of bytes in the buffer.
+ * \return The number of bytes that may be safely written to the buffer.
*/
-u32 usart_tx_n_in_buff(void) {
- u32 n;
+u32 usart_tx_n_free(void) {
/* The calculation for the number of bytes in the buffer depends on whether
- * the write pointer has wrapped around the end of the buffer or not. */
+ * or not the write pointer has wrapped around the end of the buffer. */
if (wr >= rd)
- n = wr - rd;
+ return USART_TX_BUFFER_LEN - 1 - (wr - rd);
else
- n = USART_TX_BUFFER_LEN - (rd - wr);
-
- return n;
+ return (rd - wr) - 1;
}
/** Helper function that schedules a new transfer with the DMA controller if
@@ -175,11 +170,9 @@ void dma2_stream7_isr() {
* \return The number of bytes that will be written, may be less than n.
*/
u32 usart_write_dma(u8 data[], u32 n) {
- usart_tx_di();
-
/* Check if the write would cause a buffer overflow, if so only write up to
* the end of the buffer. */
- u32 n_free = USART_TX_BUFFER_LEN - 1 - usart_tx_n_in_buff();
+ u32 n_free = usart_tx_n_free();
if (n > n_free)
n = n_free;
@@ -207,8 +200,6 @@ u32 usart_write_dma(u8 data[], u32 n) {
if (!((DMA2_S7CR & DMA_SxCR_EN) || (DMA2_HISR & DMA_HISR_TCIF7)))
dma_schedule();
- usart_tx_ei();
-
return n;
}
Please sign in to comment.
Something went wrong with that request. Please try again.