add doxygen documentation

This commit is contained in:
King Kévin 2016-03-24 10:37:42 +01:00
parent d6f3efb001
commit 3a0d9e6186
14 changed files with 2543 additions and 171 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
*.elf
*.bin
*.swp
doc

2303
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ BOARD = SYSTEM_BOARD
# source files
CSRC = $(wildcard *.c)
CHDR = $(wildcard *.h)
OBJ = $(patsubst %.c,%.o,$(CSRC))
# figure out based on the includes which library files are used in the main CSRC files
DEPENDENCIES = $(patsubst %.c,%.inc,$(CSRC))
@ -39,6 +40,7 @@ LIB = lib
# the library files to use
# this will be populated using includes based DEPENDENCIES
LIB_CSRC =
LIB_CHDR = $(patsubst %.c,%.h,$(LIB_CSRC))
LIB_OBJ = $(patsubst %.c,%.o,$(LIB_CSRC))
# populates LIB_CSRC based on the library files used
-include $(DEPENDENCIES)
@ -164,6 +166,10 @@ list: $(BINARY).list
%.inc: %.d
$(Q)grep -o -e " ${LIB}\/[^ ]*\.h" $(<) | sed -e 's/\.h$$/.c/g' -e 's/^/LIB_CSRC +=/' > $(@)
# doxygen documentation
doc: Doxyfile $(CSRC) $(CHDR) $(LIB_CSRC) $(LIB_CHDR)
$(Q)doxygen $(<)
clean:
$(Q)$(RM) $(BINARY).elf $(BINARY).bin $(BINARY).hex $(BINARY).map $(OBJ) $(LIB_OBJ) $(LIB)/*.o $(DEPENDENCIES)

View File

@ -104,4 +104,7 @@ this allows to restart the bootloader and flash new firmware using DFU.
to reset the board run `make reset`.
this only works if the USB CDC ACM run correctly and the micro-controller isn't stuck.
documentation
=============
to generate doxygen documentation run `make doc`.

View File

@ -12,36 +12,40 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/** @brief global definitions and methods
* @file global.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
*/
#pragma once
#include <libopencm3/stm32/gpio.h> // GPIO defines
#include <libopencm3/cm3/nvic.h> // interrupt defines
#include <libopencm3/stm32/exti.h> // external interrupt defines
/* get the length of an array */
/** get the length of an array */
#define LENGTH(x) (sizeof(x) / sizeof((x)[0]))
/* LED pin */
/* board LED GPIO */
#if defined(SYSTEM_BOARD)
/* on system board LED is on pin 11/PA1 */
/** on system board LED is on pin 11/PA1 */
#define LED_RCC RCC_GPIOA
#define LED_PORT GPIOA
#define LED_PIN GPIO1
#elif defined(BLUE_PILL)
/* on minimum system LED is on pin 2/PC13 */
/** on minimum system LED is on pin 2/PC13 */
#define LED_RCC RCC_GPIOC
#define LED_PORT GPIOC
#define LED_PIN GPIO13
#elif defined (MAPLE_MINI)
/* on maple mini LED is on pin 19/PB1 */
/** on maple mini LED is on pin 19/PB1 */
#define LED_RCC RCC_GPIOB
#define LED_PORT GPIOB
#define LED_PIN GPIO1
#endif
/* user button */
/* board user button GPIO */
#if defined(MAPLE_MINI)
/* on maple mini button is on 32/PB8 */
/** on maple mini user button is on 32/PB8 */
#define BUTTON_RCC RCC_GPIOB
#define BUTTON_PORT GPIOB
#define BUTTON_PIN GPIO8
@ -50,14 +54,18 @@
#define BUTTON_ISR exti9_5_isr
#endif
/* switch on LED */
/** @brief switch on board LED */
void led_on(void);
/* switch off LED */
/** @brief switch off board LED */
void led_off(void);
/* toggle LED */
/** @brief toggle board LED */
void led_toggle(void);
/* default output (i.e. for printf) */
/** @brief default printf output */
int _write(int file, char *ptr, int len);
/* print binary as string */
/** @brief get binary representation of a number
* @param[in] binary number to represent in binary
* @param[in] rjust justify representation with leading zeros
* @return string with binary representation of the number
*/
char* b2s(uint32_t binary, uint8_t rjust);

View File

@ -12,9 +12,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library is used to drive a WS2812b LED chain */
/* peripherals used: SPI , timer, DMA (check source for details) */
/** @brief library to drive a WS2812b LED chain (code)
* @file led_ws2812b.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: SPI @ref led_ws2812b_spi, timer @ref led_ws2812b_timer, DMA @ref led_ws2812b_dma
*/
/* standard libraries */
#include <stdint.h> // standard integer types
@ -32,38 +35,50 @@
#include "led_ws2812b.h" // LED WS2812b library API
#include "global.h" // global definitions
/* WS2812b peripheral configuration */
#define WS2812B_SPI SPI1
#define WS2812B_SPI_DR SPI1_DR
#define WS2812B_SPI_RCC RCC_SPI1
#define WS2812B_SPI_PORT GPIOA
#define WS2812B_SPI_CLK GPIO_SPI1_SCK // connect PWM output to clock input on PA5
#define WS2812B_SPI_DOUT GPIO_SPI1_MISO // connect WS2812b DIN to MISO pin PA6
#define WS2812B_TIMER TIM3
#define WS2812B_TIMER_RCC RCC_TIM3
#define WS2812B_TIMER_OC TIM_OC3
#define WS2812B_CLK_RCC RCC_GPIOB
#define WS2812B_CLK_PORT GPIOB
#define WS2812B_CLK_PIN GPIO_TIM3_CH3 // connect SPI clock input to PWM clock output PB0
#define WS2812B_DMA DMA1 // DMA1 supports SPI1_TX interrupt
#define WS2812B_DMA_RCC RCC_DMA1 // follows previous definition
#define WS2812B_DMA_CH DMA_CHANNEL3 // only DMA1 channel 3 supports SPI1_TX interrupt
#define WS2812B_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ // follows previous definition
#define WS2812B_DMA_ISR dma1_channel3_isr // follows previous definition
/** peripheral configuration */
/** @defgroup led_ws2812b_spi SPI peripheral used to control the WS2812b LEDs
* @{
*/
#define WS2812B_SPI SPI1 /**< SPI peripheral */
#define WS2812B_SPI_DR SPI1_DR /**< SPI data register for the DMA */
#define WS2812B_SPI_RCC RCC_SPI1 /**< SPI peripheral clock */
#define WS2812B_SPI_PORT GPIOA /**< SPI port */
#define WS2812B_SPI_CLK GPIO_SPI1_SCK /**< SPI clock pin (PA5), connect to PWM output */
#define WS2812B_SPI_DOUT GPIO_SPI1_MISO /**< SPI data pin (PA6), connect to WS2812b DIN */
/** @} */
/** @defgroup led_ws2812b_timer timer peripheral used to generate SPI clock
* @{
*/
#define WS2812B_TIMER TIM3 /**< timer peripheral */
#define WS2812B_TIMER_RCC RCC_TIM3 /**< timer peripheral clock */
#define WS2812B_TIMER_OC TIM_OC3 /**< timer output compare used to set PWM frequency */
#define WS2812B_CLK_RCC RCC_GPIOB /**< timer port peripheral clock */
#define WS2812B_CLK_PORT GPIOB /**< timer port */
#define WS2812B_CLK_PIN GPIO_TIM3_CH3 /**< timer pin to output PWM (PB0), connect to SPI clock input */
/** @} */
/** @defgroup led_ws2812b_dma DMA peripheral used to send the data
* @{
*/
#define WS2812B_DMA DMA1 /**< DMA peripheral to put data for WS2812b LED in SPI queue (only DMA1 supports SPI1_TX interrupt) */
#define WS2812B_DMA_RCC RCC_DMA1 /**< DMA peripheral clock */
#define WS2812B_DMA_CH DMA_CHANNEL3 /**< DMA channel (only DMA1 channel 3 supports SPI1_TX interrupt) */
#define WS2812B_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ /**< DMA channel interrupt signal */
#define WS2812B_DMA_ISR dma1_channel3_isr /**< DMA channel interrupt service routine */
/** @} */
/* template to encode one byte
* for each WS2812b bit which needs to be transfered we require to transfer 3 SPI bits
* the first SPI bit is the high start of the WS2812b bit frame
* the second SPI bit determines if the WS2812b bit is a 0 or 1
* the third SPI bit is the last part of the WS2812b bit frame, which is always low
* only the first 24 bits (3*8) are used */
#define WS2812B_SPI_TEMPLATE 0x92492400 //0b10010010010010010010010000000000
/** @brief bit template to encode one byte to be shifted out by SPI to the WS2812b LEDs
* @details For each WS2812b bit which needs to be transfered we require to transfer 3 SPI bits.
* The first SPI bit is the high start of the WS2812b bit frame.
* The second SPI bit determines if the WS2812b bit is a 0 or 1.
* The third SPI bit is the last part of the WS2812b bit frame, which is always low.
* Only the first 24 bits (3*8) are used.
* The binary pattern is 0b10010010010010010010010000000000
*/
#define WS2812B_SPI_TEMPLATE 0x92492400
uint8_t ws2812b_data[WS2812B_LEDS*3*3+40*3/8] = {0}; // SPI encode data to be shifted out for WS2812b + the 50us reset
uint8_t ws2812b_data[WS2812B_LEDS*3*3+40*3/8] = {0}; /**< data encoded to be shifted out by SPI for the WS2812b, pulse the 50us reset */
static volatile bool transmit_flag = false; // is transmission ongoing
/* set color of a single LED
* transmission needs to be done separately */
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue)
{
// verify the led exists
@ -90,7 +105,6 @@ void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue)
}
}
/* transmit colors to LEDs */
void ws2812b_transmit(void)
{
while (transmit_flag) { // wait for previous transmission to complete
@ -108,7 +122,6 @@ void ws2812b_transmit(void)
timer_enable_counter(WS2812B_TIMER); // start timer to generate clock
}
/* setup WS2812b LED controller */
void ws2812b_setup(void)
{
/* setup timer to generate clock of (using PWM): 800kHz*3 */
@ -160,7 +173,7 @@ void ws2812b_setup(void)
ws2812b_transmit(); // set LEDs
}
/* data transmission finished */
/** @brief DMA interrupt service routine to stop transmission after it finished */
void WS2812B_DMA_ISR(void)
{
if (dma_get_interrupt_flag(WS2812B_DMA, WS2812B_DMA_CH, DMA_TCIF)) { // transfer completed

View File

@ -12,18 +12,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library is used to drive a WS2812b LED chain */
/* peripherals used: SPI , timer, DMA (check source for details) */
/** @brief library to drive a WS2812b LED chain (API)
* @file led_ws2812b.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: SPI @ref led_ws2812b_spi, timer @ref led_ws2812b_timer, DMA @ref led_ws2812b_dma
*/
#pragma once
/* number of LEDs */
/** number of LEDs on the WS2812b strip */
#define WS2812B_LEDS 60
/* set color of a single LED
* transmission needs to be done separately */
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue);
/* transmit colors to LEDs */
void ws2812b_transmit(void);
/* setup WS2812b LED controller */
/** @brief setup WS2812b LED driver */
void ws2812b_setup(void);
/** @brief set color of a single LED
* @param[in] led the LED number to set the color
* @param[in] red the red color value to set on the LED
* @param[in] green the green color value to set on the LED
* @param[in] blue the blue color value to set on the LED
* @note transmission needs to be done separately
*/
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue);
/** @brief transmit color values to WS2812b LEDs */
void ws2812b_transmit(void);

View File

@ -12,11 +12,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** @file rtc_ds1307.c
/** @brief library to communicate with the Maxim DS1307 I2C RTC IC (code)
* @file rtc_ds1307.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @brief this library handles communication with the I2C RTC IC Maxim DS1307
* peripherals used: I2C @ref rtc_ds1307_i2c
* @note peripherals used: I2C @ref rtc_ds1307_i2c
*/
/* standard libraries */
@ -34,26 +34,19 @@
#include "global.h" // global utilities
#include "rtc_ds1307.h" // RTC header and definitions
/** @defgroup trc_ds1307_i2c I2C port used to communication with the DS1307 RTC IC
/** @defgroup rtc_ds1307_i2c I2C peripheral used to communication with the DS1307 RTC IC
* @{
*/
/** I2C peripheral */
#define I2C I2C1
/** I2C peripheral clock */
#define I2C_RCC RCC_I2C1
/** I2C peripheral interrupt */
#define I2C_IRQ NVIC_I2C1_EV_IRQ
/** I2C event interrupt service routine */
#define I2C_ISR i2c1_ev_isr
/** I2C peripheral port */
#define I2C_PORT GPIOB
/** I2C peripheral data pin (PB7) */
#define I2C_PIN_SDA GPIO_I2C1_SDA
/** I2C peripheral clock pin (PB6) */
#define I2C_PIN_SCL GPIO_I2C1_SCL
#define I2C I2C1 /**< I2C peripheral */
#define I2C_RCC RCC_I2C1 /**< I2C peripheral clock */
#define I2C_IRQ NVIC_I2C1_EV_IRQ /**< I2C peripheral interrupt */
#define I2C_ISR i2c1_ev_isr /**< I2C event interrupt service routine */
#define I2C_PORT GPIOB /**< I2C peripheral port */
#define I2C_PIN_SDA GPIO_I2C1_SDA /**< I2C peripheral data pin (PB7) */
#define I2C_PIN_SCL GPIO_I2C1_SCL /**< I2C peripheral clock pin (PB6) */
/** @} */
/** DS1307 I2C address (fixed) */
#define I2C_ADDR 0x68 //0b1101000
#define I2C_ADDR 0x68 /**< DS1307 I2C address (fixed to 0b1101000) */
void rtc_setup(void)
{
@ -413,6 +406,7 @@ bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day
return rtc_write_memory(0, data, LENGTH(data)); // write time values on RTC
}
void I2C_ISR(void) { // I2C event ISR
/** I2C event interrupt service routine */
void I2C_ISR(void) {
// do nothing except wake up
}

View File

@ -12,12 +12,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** @file rtc_ds1307.h
/** @brief library to communicate with the Maxim DS1307 I2C RTC IC (API)
* @file rtc_ds1307.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @brief this library handles communication with the I2C RTC IC Maxim DS1307
* @todo control register and user RAM are not handled
* peripherals used: I2C @ref rtc_ds1307_i2c
* @note peripherals used: I2C @ref rtc_ds1307_i2c
*/
#pragma once
@ -42,15 +42,15 @@ uint8_t rtc_read_minutes(void);
*/
uint8_t rtc_read_hours(void);
/** @brief read day from RTC IC
* @return day (1-7) of the current time, 1 being Sunday
* @return day of the week (1-7, 1 is Sunday) of the current time, 1 being Sunday
*/
uint8_t rtc_read_day(void);
/** @brief read date from RTC IC
* @return date (day of the month, 1-31) of the current time
* @return day of the month (1-31) of the current time
*/
uint8_t rtc_read_date(void);
/** @brief read month from RTC IC
* @return month (1-12) of the current time
* @return month of the year (1-12) of the current time
*/
uint8_t rtc_read_month(void);
/** @brief read year from RTC IC
@ -70,48 +70,48 @@ bool rtc_oscillator_disable(void);
*/
bool rtc_oscillator_enable(void);
/** @brief write seconds into RTC IC
* @param[in] number of seconds (0-59)
* @param[in] seconds number of seconds (0-59)
* @return if write succeeded
*/
bool rtc_write_seconds(uint8_t seconds);
/** @brief write minutes into RTC IC
* @param[in] number of minutes (0-59)
* @param[in] minutes number of minutes (0-59)
* @return if write succeeded
*/
bool rtc_write_minutes(uint8_t minutes);
/** @brief write hours into RTC IC
* @param[in] number of hours (0-23)
* @param[in] hours number of hours (0-23)
* @return if write succeeded
*/
bool rtc_write_hours(uint8_t hours);
/** @brief write day into RTC IC
* @param[in] day (1-7, 1 is Sunday)
* @param[in] day day of the week (1-7, 1 is Sunday)
* @return if write succeeded
*/
bool rtc_write_day(uint8_t day);
/** @brief write date into RTC IC
* @param[in] date (day of the month, 1-31)
* @param[in] date day of the month (1-31)
* @return if write succeeded
*/
bool rtc_write_date(uint8_t date);
/** @brief write month into RTC IC
* @param[in] month (1-12)
* @param[in] month month of the year (1-12)
* @return if write succeeded
*/
bool rtc_write_month(uint8_t month);
/** @brief write year into RTC IC
* @param[in] year (2000-2099)
* @param[in] year year (2000-2099)
* @return if write succeeded
*/
bool rtc_write_year(uint16_t year);
/** @brief write time into RTC IC
* @param[in] number of seconds (0-59)
* @param[in] number of minutes (0-59)
* @param[in] number of hours (0-23)
* @param[in] day (1-7, 1 is Sunday)
* @param[in] date (day of the month, 1-31)
* @param[in] month (1-12)
* @param[in] year (2000-2099)
* @param[in] seconds number of seconds (0-59)
* @param[in] minutes number of minutes (0-59)
* @param[in] hours number of hours (0-23)
* @param[in] day day of the week (1-7, 1 is Sunday)
* @param[in] date day of the month (1-31)
* @param[in] month month of the year (1-12)
* @param[in] year year (2000-2099)
* @return if write succeeded
*/
bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day, uint8_t date, uint8_t month, uint16_t year);

View File

@ -12,9 +12,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library handles USART communication */
/* peripherals used: USART (check source for details) */
/** @brief library for USART communication (code)
* @file usart.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: USART @ref usart
*/
/* standard libraries */
#include <stdint.h> // standard integer types
@ -30,18 +33,19 @@
#include "usart.h" // USART header and definitions
/* which USART to use */
#define USART USART1
#define USART_RCC RCC_USART1
#define USART_IRQ NVIC_USART1_IRQ
#define USART_PORT GPIOA
#define USART_PIN_TX GPIO_USART1_TX
#define USART_PIN_RX GPIO_USART1_RX
/** @defgroup usart USART peripheral used for UART communication
* @{
*/
#define USART USART1 /**< USART peripheral */
#define USART_RCC RCC_USART1 /**< USART peripheral clock */
#define USART_IRQ NVIC_USART1_IRQ /**< USART peripheral interrupt signal */
#define USART_ISR usart1_isr /**< USART interrupt service routine */
#define USART_PORT GPIOA /**< USART port */
#define USART_PIN_TX GPIO_USART1_TX /**< USART transmit pin (PA9) */
#define USART_PIN_RX GPIO_USART1_RX /**< USART receive pin (PA10) */
/** @} */
/* serial baudrate, in bits per second (with 8N1 8 bits, no parity bit, 1 stop bit settings) */
#define USART_BAUDRATE 115200
/* RX and TX buffer sizes */
#define USART_BUFFER 128
#define USART_BAUDRATE 115200 /**< serial baudrate, in bits per second (with 8N1 8 bits, no parity bit, 1 stop bit settings) */
/* input and output ring buffer, indexes, and available memory */
static uint8_t rx_buffer[USART_BUFFER] = {0};
@ -50,10 +54,8 @@ static volatile uint8_t rx_used = 0;
static uint8_t tx_buffer[USART_BUFFER] = {0};
static volatile uint8_t tx_i = 0;
static volatile uint8_t tx_used = 0;
/* show the user how much data received over USART is ready */
volatile uint8_t usart_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it
/* setup USART port */
void usart_setup(void)
{
/* enable USART I/O peripheral */
@ -82,14 +84,12 @@ void usart_setup(void)
usart_received = 0;
}
/* put character on USART (blocking) */
void usart_putchar_blocking(char c)
{
usart_flush(); // empty buffer first
usart_send_blocking(USART, c); // send character
}
/* ensure all data has been transmitted (blocking) */
void usart_flush(void)
{
while (tx_used) { // idle until buffer is empty
@ -98,7 +98,6 @@ void usart_flush(void)
usart_wait_send_ready(USART); // wait until transmit register is empty (transmission might not be complete)
}
/* get character from USART (blocking) */
char usart_getchar(void)
{
while (!rx_used) { // idle until data is available
@ -111,7 +110,6 @@ char usart_getchar(void)
return to_return;
}
/* put character on USART (non-blocking until buffer is full) */
void usart_putchar_nonblocking(char c)
{
while (tx_used>=sizeof(tx_buffer)) { // idle until buffer has some space
@ -123,14 +121,9 @@ void usart_putchar_nonblocking(char c)
usart_enable_tx_interrupt(USART); // enable transmit interrupt
}
#if (USART==USART1)
void usart1_isr(void)
#elif (USART==USART2)
void usart2_isr(void)
#elif (USART==USART3)
void usart3_isr(void)
#endif
{ // USART interrupt
/** @brief USART interrupt service routine called when data has been transmitted or received */
void USART_ISR(void)
{
if (usart_get_interrupt_source(USART, USART_SR_TXE)) { // data has been transmitted
if (!tx_used) { // no data in the buffer to transmit
usart_disable_tx_interrupt(USART); // disable transmit interrupt

View File

@ -12,21 +12,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library handles USART communication */
/* peripherals used: USART (check source for details) */
/** @brief library for USART communication (API)
* @file usart.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @note peripherals used: USART @ref usart
*/
#pragma once
/* show the user how much received is available */
/** transmit and receive buffer sizes */
#define USART_BUFFER 128
/** how many bytes available in the received buffer since last read */
extern volatile uint8_t usart_received;
/* setup USART port */
/** @brief setup USART peripheral */
void usart_setup(void);
/* put character on USART (blocking) */
/** @brief send character over USART (blocking)
* @param[in] c character to send
* @note blocks until character transmission started */
void usart_putchar_blocking(char c);
/* ensure all data has been transmitted (blocking) */
/** @brief ensure all data has been transmitted (blocking)
* @note block until all data has been transmitted
*/
void usart_flush(void);
/* get character from USART (blocking) */
/** @brief get character received over USART (blocking)
* @return character received over USART
* @note blocks until character is received over USART when received buffer is empty
*/
char usart_getchar(void);
/* put character on USART (non-blocking until buffer is full) */
/** @brief send character over USART (non-blocking)
* @param[in] c character to send
* @note blocks if transmit buffer is full, else puts in buffer and returns
*/
void usart_putchar_nonblocking(char c);

View File

@ -12,8 +12,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library handles the USB CDC ACM */
/** @brief library for USB CDC ACM communication (code)
* @file usb_cdcacm.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
*/
/* standard libraries */
#include <stdint.h> // standard integer types
@ -31,8 +34,8 @@
#include "usb_cdcacm.h" // USB CDC ACM header and definitions
/* USB devices descriptor
* as defined in USB CDC specification section 5
/** @brief USB CDC ACM device descriptor
* @note as defined in USB CDC specification section 5
*/
static const struct usb_device_descriptor device_descriptor = {
.bLength = USB_DT_DEVICE_SIZE, // the size of this header in bytes, 18
@ -51,6 +54,9 @@ static const struct usb_device_descriptor device_descriptor = {
.bNumConfigurations = 1, // the number of possible configurations this device has
};
/** @brief USB CDC ACM data endpoints
* @note as defined in USB CDC specification section 5
*/
static const struct usb_endpoint_descriptor data_endpoints[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, // the size of the endpoint descriptor in bytes
.bDescriptorType = USB_DT_ENDPOINT, // a value of 5 indicates that this describes an endpoint
@ -67,9 +73,8 @@ static const struct usb_endpoint_descriptor data_endpoints[] = {{
.bInterval = 1, // the frequency, in number of frames, that we're going to be sending data
}};
/* This notification endpoint isn't implemented. According to CDC spec its
* optional, but its absence causes a NULL pointer dereference in Linux
* cdc_acm driver.
/** @brief USB CDC ACM communication endpoints
* @note This notification endpoint isn't implemented. According to CDC spec its optional, but its absence causes a NULL pointer dereference in Linux cdc_acm driver
*/
static const struct usb_endpoint_descriptor communication_endpoints[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, // the size of the endpoint descriptor in bytes
@ -80,8 +85,8 @@ static const struct usb_endpoint_descriptor communication_endpoints[] = {{
.bInterval = 255, // the frequency, in number of frames, that we're going to be sending data
}};
/* functional descriptor
* as defined in USB CDC specification section 5.2.3
/** @brief USB CDC ACM functional descriptor
* @note as defined in USB CDC specification section 5.2.3
*/
static const struct {
struct usb_cdc_header_descriptor header;
@ -117,8 +122,8 @@ static const struct {
},
};
/* communication class interface descriptor
* as defined in USB CDC specification section 5.1.3
/** @brief USB CDC interface descriptor
* @note as defined in USB CDC specification section 5.1.3
*/
static const struct usb_interface_descriptor communication_interface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
@ -137,8 +142,8 @@ static const struct usb_interface_descriptor communication_interface[] = {{
.extralen = sizeof(cdcacm_functional_descriptors),
}};
/* data class interface descriptor
* as defined in USB CDC specification section 5.1.3
/** @brief USB CDC ACM data class interface descriptor
* @note as defined in USB CDC specification section 5.1.3
*/
static const struct usb_interface_descriptor data_interface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
@ -154,6 +159,7 @@ static const struct usb_interface_descriptor data_interface[] = {{
.endpoint = data_endpoints,
}};
/** @brief USB CDC ACM interface descriptor */
static const struct usb_interface interfaces[] = {{
.num_altsetting = 1,
.altsetting = communication_interface,
@ -162,6 +168,7 @@ static const struct usb_interface interfaces[] = {{
.altsetting = data_interface,
}};
/** @brief USB CDC ACM configuration descriptor */
static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE, // the length of this header in bytes
.bDescriptorType = USB_DT_CONFIGURATION, // a value of 2 indicates that this is a configuration descriptor
@ -175,17 +182,19 @@ static const struct usb_config_descriptor config = {
.interface = interfaces, // pointer to an array of interfaces
};
/* string table (starting with index 1) */
const char *usb_strings[] = {
/** @brief USB string table
* @note starting with index 1
*/
static const char *usb_strings[] = {
"CuVoodoo",
"CDC-ACM",
"STM32F1",
};
/* buffer to be used for control requests */
/** buffer to be used for control requests */
static uint8_t usbd_control_buffer[128];
/* structure holding all the info related to the USB device */
/** structure holding all the info related to the USB device */
static usbd_device *usb_device;
/* input and output ring buffer, indexes, and available memory */
@ -195,10 +204,9 @@ static volatile uint8_t rx_used = 0;
static uint8_t tx_buffer[CDCACM_BUFFER] = {0};
static volatile uint8_t tx_i = 0;
static volatile uint8_t tx_used = 0;
/* show the user how much data received over USB is ready */
volatile uint8_t cdcacm_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it
/* disconnect USB by pulling down D+ to for re-enumerate */
/** @brief disconnect USB by pulling down D+ to for re-enumerate */
static void usb_disconnect(void)
{
/* short USB disconnect to force re-enumerate */
@ -222,6 +230,9 @@ static void usb_disconnect(void)
#endif
}
/** @brief incoming USB CDC ACM control request
* @note resets device when configured with 5 bits
*/
static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{
(void)complete;
@ -338,7 +349,6 @@ void cdcacm_setup(void)
usbd_ep_write_packet(usb_device, 0x82, NULL, 0);
}
/* get character from USB CDC ACM (blocking) */
char cdcacm_getchar(void)
{
while (!rx_used) { // idle until data is available
@ -351,7 +361,6 @@ char cdcacm_getchar(void)
return to_return;
}
/* put character on USB CDC ACM (blocking) */
void cdcacm_putchar(char c)
{
if (tx_used<sizeof(tx_buffer)) { // buffer not full
@ -364,10 +373,12 @@ void cdcacm_putchar(char c)
usbd_ep_write_packet(usb_device, 0x82, NULL, 0); // trigger tx (not sure why cdcacm_data_tx_cb doesn't work else)
}
/** @brief USB interrupt service routine called on wake-up event */
void usb_wakeup_isr(void) {
usbd_poll(usb_device);
}
/** @brief USB interrupt service routine called when data is received */
void usb_lp_can_rx0_isr(void) {
usbd_poll(usb_device);
}

View File

@ -12,18 +12,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* this library handles the USB CDC ACM */
/** @brief library for USB CDC ACM communication (API)
* @file usb_cdcacm.h
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
*/
#pragma once
/* RX buffer size */
/** transmit and receive buffer sizes */
#define CDCACM_BUFFER 128
/* show the user how much received is available */
/** how many bytes available in the received buffer since last read */
extern volatile uint8_t cdcacm_received;
/* setup USB CDC ACM */
/** @brief setup USB CDC ACM peripheral */
void cdcacm_setup(void);
/* get character from USB CDC ACM (blocking) */
/** @brief get character received over USB (blocking)
* @return character received over USB
* @note blocks until character is received over USB when received buffer is empty
*/
char cdcacm_getchar(void);
/* put character on USB CDC ACM (blocking) */
/** @brief send character over USB (non-blocking)
* @param[in] c character to send
* @note blocks if transmit buffer is full, else puts in buffer and returns
*/
void cdcacm_putchar(char c);

24
main.c
View File

@ -13,11 +13,12 @@
*
*/
/** @file main.c
* @author King Kévin <kingkevin@cuvoodoo.info>
* @date 2016
* @brief show the time on a LED strip
* the LED strip consists of 60 WS2812b LEDs
* the time is read from a DS1307 RTC module
@author King Kévin <kingkevin@cuvoodoo.info>
@date 2016
@brief show the time on a LED strip
The LED strip consists of 60 WS2812b LEDs.
The time is read from a DS1307 RTC module.
*/
/* standard libraries */
@ -42,8 +43,11 @@
#include "led_ws2812b.h" // WS2812b LEDs utilities
#include "rtc_ds1307.h" // Real Time Clock DS1307 utilities
/* flag set in interrupts to be processed in main task */
volatile bool button_flag = false; // button has been pressed
/** @defgroup main_flags flag set in interrupts to be processed in main task
@{
*/
volatile bool button_flag = false; /**< flag set if board user button has been pressed */
/** @} */
/** the number of ticks in one second
* @note the other values are derived from this value @ref main_ticks
@ -63,7 +67,8 @@ const uint32_t ticks_hour = 60*60*TICKS_PER_SECOND;
const uint32_t ticks_midday = 12*60*60*TICKS_PER_SECOND;
/** @} */
uint8_t clock_leds[WS2812B_LEDS*3] = {0}; // RGB values for the WS2812b clock LEDs
/** RGB values for the WS2812b clock LEDs */
uint8_t clock_leds[WS2812B_LEDS*3] = {0};
/** @brief default printf output */
int _write(int file, char *ptr, int len)
@ -215,6 +220,9 @@ static void leds_set(void)
}
}
/** @brief program entry point
* this is the firmware function started by the micro-controller
*/
int main(void)
{
SCB_VTOR = (uint32_t) 0x08002000; // relocate vector table because of the bootloader