Microchip® Advanced Software Framework

dbg_print.c File Reference

Debug print implementation.

Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.

#include "dbg_print.h"
#include <gclk.h>
#include <sercom.h>
#include <status_codes.h>
#include <string.h>
#include <system.h>
#include <usart.h>
#include <FreeRTOS.h>
#include <semphr.h>
#include <task.h>

Functions

static void _dbg_interrupt_handler (uint8_t dummy)
 SERCOM UART interrupt handler. More...
 
enum status_code dbg_init (void)
 Initialize and enable debug UART. More...
 
void dbg_print_char (const char out_char)
 Print a single character. More...
 
void dbg_print_hexint (uint32_t out_int)
 Print an integer as hex digits. More...
 
void dbg_print_str (const char *out_str)
 Print a zero-terminated string. More...
 
void dbg_sprint_hexint (char *out_str, uint32_t out_int)
 Write an integer as hex digits (ASCII) into string. More...
 
Access lock/unlock
static void _dbg_wait_for_lock (void)
 Wait indefinitely to lock access. More...
 
static void _dbg_unlock (void)
 Unlock access. More...
 
UART start/stop
static void _dbg_start_uart (void)
 Start UART by enabling DRE interrupt. More...
 
static void _dbg_stop_uart (void)
 Stop UART by disabling DRE interrupt. More...
 
Internal buffer helpers
static dbg_buffer_space_t _dbg_get_free_buffer_space (void)
 Get current space in print buffer. More...
 
static void _dbg_write_str_to_buffer (const char *str, dbg_buffer_space_t length)
 Write string to the print buffer. More...
 
static dbg_buffer_space_t _dbg_request_free_space (dbg_buffer_space_t length)
 Issue request for free buffer space. More...
 
static void _dbg_wait_for_requested_space (void)
 Wait for requested space to free up. More...
 
static void _dbg_putstr (const char *str, size_t length)
 Put a string into the print buffer. More...
 

Variables

Internal data
static SercomUsart *const sercom_uart = &(CONF_DBG_PRINT_SERCOM->USART)
 Pointer to SERCOM USART instance to use. More...
 
static uint8_t dbg_buffer [DBG_BUFFER_SIZE]
 Circular print buffer. More...
 
static dbg_buffer_space_t buffer_head
 Print buffer head (write index) More...
 
static dbg_buffer_space_t buffer_tail
 Print buffer tail (read index) More...
 
static dbg_buffer_space_t requested_space
 Variable for buffer space requests. More...
 
static xSemaphoreHandle dbg_is_free
 Mutex to prevent concurrent writes to print buffer. More...
 
static xSemaphoreHandle requested_space_is_free
 Semaphore to signal buffer has requested space. More...
 

Convenience macros

#define DBG_BUFFER_SIZE   (CONF_DBG_PRINT_BUFFER_SIZE)
 Size of print buffer (must be power of 2) More...
 
#define DBG_BUFFER_SPACE   (DBG_BUFFER_SIZE - 1)
 Maximum number of simultaneously queued bytes in print buffer. More...
 
#define DBG_BUFFER_MASK   (DBG_BUFFER_SIZE - 1)
 Bitmask for print buffer head and tail. More...
 
#define TRANSLATE_NIBBLE_TO_ASCII(nibble_var)   (nibble_var) += ((nibble_var) < 0x0a) ? '0' : ('A' - 0x0a)
 Translate nibble (4-bit) value to ASCII symbol. More...
 
typedef uint8_t dbg_buffer_space_t
 Type for buffer space and indexes. More...
 

#define DBG_BUFFER_MASK   (DBG_BUFFER_SIZE - 1)

Bitmask for print buffer head and tail.

Referenced by _dbg_get_free_buffer_space(), _dbg_interrupt_handler(), and _dbg_write_str_to_buffer().

#define DBG_BUFFER_SIZE   (CONF_DBG_PRINT_BUFFER_SIZE)

Size of print buffer (must be power of 2)

#define DBG_BUFFER_SPACE   (DBG_BUFFER_SIZE - 1)

Maximum number of simultaneously queued bytes in print buffer.

Note
This number is one less than the size of the buffer due to its circular nature. Otherwise, it would be impossible to tell whether the buffer is full or empty as computed in _dbg_get_free_buffer_space().

Referenced by _dbg_get_free_buffer_space(), and _dbg_request_free_space().

#define TRANSLATE_NIBBLE_TO_ASCII (   nibble_var)    (nibble_var) += ((nibble_var) < 0x0a) ? '0' : ('A' - 0x0a)

Translate nibble (4-bit) value to ASCII symbol.

Referenced by dbg_sprint_hexint().

typedef uint8_t dbg_buffer_space_t

Type for buffer space and indexes.

Note
This type must have at least as many bits as DBG_BUFFER_SPACE.

static dbg_buffer_space_t _dbg_get_free_buffer_space ( void  )
inlinestatic

Get current space in print buffer.

Returns
Number of free bytes in buffer.

References buffer_head, buffer_tail, DBG_BUFFER_MASK, and DBG_BUFFER_SPACE.

Referenced by _dbg_putstr().

static void _dbg_interrupt_handler ( uint8_t  dummy)
static

SERCOM UART interrupt handler.

This interrupt handler will transmit bytes from the internal print buffer until the tail (read-index) catches up with the head (write-index), at which point it will disable itself since the entire buffer will have been transmitted.

If a print function has requested more space in the buffer, this interrupt handler will also track the number of bytes that have been transmitted and give the mutex when the request has been fulfilled.

Parameters
dummyNot used. (SERCOM number passed from master interrupt handler.)

References buffer_head, buffer_tail, data, dbg_buffer, DBG_BUFFER_MASK, NULL, requested_space, requested_space_is_free, sercom_uart, and xSemaphoreGiveFromISR.

Referenced by dbg_init().

static void _dbg_putstr ( const char *  str,
size_t  length 
)
inlinestatic

Put a string into the print buffer.

This function puts a string into the print buffer, taking care to not exceed the buffer's free space. If the buffer becomes full, this function will start the UART and wait for enough space to free up until the entire string has been put into buffer.

Parameters
[in]strPointer to string to put into the print buffer.
[out]lengthLength of the string to put into the print buffer.

References _dbg_get_free_buffer_space(), _dbg_request_free_space(), _dbg_start_uart(), _dbg_stop_uart(), _dbg_wait_for_requested_space(), _dbg_write_str_to_buffer(), and min.

Referenced by dbg_print_char(), dbg_print_hexint(), and dbg_print_str().

static dbg_buffer_space_t _dbg_request_free_space ( dbg_buffer_space_t  length)
inlinestatic

Issue request for free buffer space.

This function will issue a request for _dbg_interrupt_handler() to notify when either the specified number or all (DBG_BUFFER_SPACE) bytes have been freed in a full buffer, depending on which is smaller. The number of bytes that were actually requested is returned by this function.

Parameters
[in]lengthDesired number of bytes to free up.
Returns
The number of bytes which were requested
Return values
DBG_BUFFER_SPACEif length was greater than what buffer can contain.
lengthif desired length is less than DBG_BUFFER_SPACE.
Attention
The print buffer should be full when this function is called because requesting more buffer space than is currently used in will cause _dbg_wait_for_requested_space() to never return.
Precondition
_dbg_stop_uart() must be called before this function.
Postcondition
_dbg_wait_for_requested_space() must be used to detect when the space has been freed.

References DBG_BUFFER_SPACE, length, min, and requested_space.

Referenced by _dbg_putstr().

static void _dbg_start_uart ( void  )
inlinestatic

Start UART by enabling DRE interrupt.

References sercom_uart.

Referenced by _dbg_putstr().

static void _dbg_stop_uart ( void  )
inlinestatic

Stop UART by disabling DRE interrupt.

References sercom_uart.

Referenced by _dbg_putstr().

static void _dbg_unlock ( void  )
inlinestatic

Unlock access.

References dbg_is_free, and xSemaphoreGive.

Referenced by dbg_print_char(), dbg_print_hexint(), and dbg_print_str().

static void _dbg_wait_for_lock ( void  )
inlinestatic

Wait indefinitely to lock access.

This function will try to take the dbg_is_free mutex, and will wait an indefinite amount of time for it.

References dbg_is_free, and xSemaphoreTake.

Referenced by dbg_print_char(), dbg_print_hexint(), and dbg_print_str().

static void _dbg_wait_for_requested_space ( void  )
inlinestatic

Wait for requested space to free up.

This function will wait indefinitely for _dbg_interrupt_handler() to free up the number of bytes requested earlier using _dbg_request_free_space() in the print buffer.

Attention
If the previous call to _dbg_request_free_space() returned 0, this function must not be called, because it will never return.
Precondition
_dbg_request_free_space() must be called before this function.
_dbg_start_uart() must be called before this function, for the buffer to be processed and space freed up.

References requested_space_is_free, and xSemaphoreTake.

Referenced by _dbg_putstr().

static void _dbg_write_str_to_buffer ( const char *  str,
dbg_buffer_space_t  length 
)
inlinestatic

Write string to the print buffer.

This is a helper function for copying a string into the print buffer, using circular buffer indexing.

Parameters
[in]strPointer to string to write into buffer. [in] length Number of string bytes to write.
Note
This function does not check if the specified length is larger than the free space in the print buffer. That must be checked by the calling code.

References Assert, buffer_head, dbg_buffer, and DBG_BUFFER_MASK.

Referenced by _dbg_putstr().

dbg_buffer_space_t buffer_head
static

Print buffer head (write index)

Referenced by _dbg_get_free_buffer_space(), _dbg_interrupt_handler(), and _dbg_write_str_to_buffer().

dbg_buffer_space_t buffer_tail
static

Print buffer tail (read index)

Referenced by _dbg_get_free_buffer_space(), and _dbg_interrupt_handler().

uint8_t dbg_buffer[DBG_BUFFER_SIZE]
static

Circular print buffer.

Referenced by _dbg_interrupt_handler(), and _dbg_write_str_to_buffer().

xSemaphoreHandle dbg_is_free
static

Mutex to prevent concurrent writes to print buffer.

Referenced by _dbg_unlock(), _dbg_wait_for_lock(), and dbg_init().

dbg_buffer_space_t requested_space
static

Variable for buffer space requests.

Referenced by _dbg_interrupt_handler(), and _dbg_request_free_space().

xSemaphoreHandle requested_space_is_free
static

Semaphore to signal buffer has requested space.

Referenced by _dbg_interrupt_handler(), _dbg_wait_for_requested_space(), and dbg_init().

SercomUsart* const sercom_uart = &(CONF_DBG_PRINT_SERCOM->USART)
static

Pointer to SERCOM USART instance to use.

Referenced by _dbg_interrupt_handler(), _dbg_start_uart(), _dbg_stop_uart(), and dbg_init().