diff --git a/docs/pdfs/SPL.pdf b/docs/pdfs/SPL.pdf new file mode 100644 index 0000000..898f5fd Binary files /dev/null and b/docs/pdfs/SPL.pdf differ diff --git a/software/os/queues.c b/software/os/queues.c new file mode 100644 index 0000000..cb2d231 --- /dev/null +++ b/software/os/queues.c @@ -0,0 +1,72 @@ +/* + * queues.c + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#include "stdlib.h" +#include "stm32f10x.h" +#include "queues.h" +#include +#include + +static inline uint8_t osQFull(osQUEUE_t* q); + +static inline uint8_t osQEmpty(osQUEUE_t* q); + +static inline void osWrapArroundInc(uint8_t* i); + +void osQInit(osQUEUE_t* q, size_t ivarsize, void* istart) +{ + q->read_p = 0; + q->write_p = 0; + q->varsize = ivarsize; + q->start = istart; +} + +uint8_t osEnqueue(osQUEUE_t* q, void* data) +{ + if(osQFull(q)) + return 0; + else + { + /* Copy queue element to where it belongs. */ + memcpy( ( q->start + (q->write_p)*(q->varsize) ), data, q->varsize); + osWrapArroundInc( &(q->write_p) ); + } + return 1; +} + + +uint8_t osDequeue(osQUEUE_t* q, void* data) +{ + if(osQEmpty(q)) + return 0; + else + { + memcpy(data, ( q->start + (q->read_p)*(q->varsize) ), q->varsize); + osWrapArroundInc( &(q->read_p) ); + } + return 1; +} + +static inline uint8_t osQFull(osQUEUE_t* q) +{ + uint8_t next = q->write_p; + osWrapArroundInc(&next); + return(next == q->read_p); +} + +static inline uint8_t osQEmpty(osQUEUE_t* q) +{ + return(q->write_p == q->read_p); +} + +static inline void osWrapArroundInc(uint8_t* i) +{ + if( (*i) < MAX_QUEUE_SIZE ) + (*i)++; + else + (*i) = 0; +} diff --git a/software/os/queues.h b/software/os/queues.h new file mode 100644 index 0000000..f9b276f --- /dev/null +++ b/software/os/queues.h @@ -0,0 +1,31 @@ +/* + * queues.h + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#ifndef OS_QUEUES_H_ +#define OS_QUEUES_H_ + +#include "stm32f10x.h" +#include + +#define MAX_QUEUE_SIZE 64 + +typedef struct +{ + uint8_t write_p; + uint8_t read_p; + /* Gives you the possibility to use the q with every data type. */ + void* start; + size_t varsize; +} osQUEUE_t; + +void osQInit(osQUEUE_t* q, size_t ivarsize, void* istart); + +uint8_t osEnqueue(osQUEUE_t* rx_q, void* data); + +uint8_t osDequeue(osQUEUE_t* tx_q, void* data); + +#endif /* OS_QUEUES_H_ */ diff --git a/software/platform/system_timer.c b/software/platform/system_timer.c new file mode 100644 index 0000000..b2972b9 --- /dev/null +++ b/software/platform/system_timer.c @@ -0,0 +1,70 @@ +/* + * system_timer.c + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#include "stm32f10x.h" +#include "stm32f10x_flash.h" +#include "stm32f10x_rcc.h" + +#define ALIVE_PULSE_LENGTH 200 + +static volatile uint32_t ticky = 0; + +void InitAliveLED(void) +{ + /* Activate clock for peripheral. */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + + /* Initialize GPIO Pin. */ + GPIO_InitTypeDef GPIO_InitStructure ; + GPIO_StructInit (&GPIO_InitStructure ); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz ; + GPIO_Init (GPIOA , & GPIO_InitStructure ); +} + +void InitClock(void) +{ + /* Configure all clocks to max for best performance. + If there are EMI, power, or noise problems, try slowing the clocks.*/ + + /* First set the flash latency to work with our clock. + 000 Zero wait state, if 0 MHz < SYSCLK <= 24 MHz + 001 One wait state, if 24 MHz < SYSCLK <= 48 MHz + 010 Two wait states, if 48 MHz < SYSCLK <= 72 MHz */ + FLASH_SetLatency(FLASH_Latency_1); + + /* Start with HSI (High-Speed Internal) clock with 8 MHz, divide by 2 and multiply by 9 to + get maximum allowed frequency: 36 MHz + Enable PLL, wait till it's stable, then select it as system clock*/ + RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9); + RCC_PLLCmd(ENABLE); + while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} + RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); + + /* Set HCLK, PCLK1, and PCLK2 to SCLK. */ + RCC_HCLKConfig(RCC_SYSCLK_Div1); + RCC_PCLK1Config(RCC_HCLK_Div8); + RCC_PCLK2Config(RCC_HCLK_Div8); + + /* Configure Cortex-M System Tick Timer to tick every ms.*/ + SystemCoreClockUpdate(); + SysTick_Config(SystemCoreClock / 1000); +} + +void SysTick_Handler(void) +{ + static volatile uint8_t led_stat = 0; + if(ticky == ALIVE_PULSE_LENGTH) + { + led_stat = !led_stat; + GPIO_WriteBit(GPIOA, GPIO_Pin_5, led_stat); + ticky = 0; + } + else + ticky++; +} diff --git a/software/platform/system_timer.h b/software/platform/system_timer.h new file mode 100644 index 0000000..c8453e4 --- /dev/null +++ b/software/platform/system_timer.h @@ -0,0 +1,14 @@ +/* + * system_timer.h + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#ifndef PLATFORM_SYSTEM_TIMER_H_ +#define PLATFORM_SYSTEM_TIMER_H_ + +void InitAliveLED(void); +void InitClock(void); + +#endif /* PLATFORM_SYSTEM_TIMER_H_ */ diff --git a/software/platform/usart.c b/software/platform/usart.c new file mode 100644 index 0000000..348bedd --- /dev/null +++ b/software/platform/usart.c @@ -0,0 +1,144 @@ +/* + * usart.c + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#include "usart.h" +#include "../os/queues.h" +#include "stm32f10x_gpio.h" +#include "stm32f10x_usart.h" + +uint8_t rx_overflow = 0; + +osQUEUE_t usart_rx_q, usart_tx_q; + +uint8_t usart_rx_data[MAX_QUEUE_SIZE]; +uint8_t usart_tx_data[MAX_QUEUE_SIZE]; + + +void usart2Init(void) +{ + /* Enable clocks. */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA , ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + + /* Initialize used GPIOs. */ + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_StructInit(&GPIO_InitStruct); + + /* Initialize USART2_TX */ + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Init. USART2_RX */ + GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Init. USART2 peripheral. */ + USART_InitTypeDef USART_InitStructure ; + USART_StructInit(&USART_InitStructure ); + USART_InitStructure.USART_BaudRate = 9600; + USART_InitStructure.USART_WordLength = USART_StopBits_1; + USART_InitStructure.USART_Parity = USART_Parity_No; + USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + USART_Init(USART2, &USART_InitStructure); + USART_Cmd(USART2, ENABLE); + + /* Config. interrupts. */ + USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); + NVIC_EnableIRQ(USART2_IRQn); + + /* Init. SW queues. */ + osQInit(&usart_rx_q, sizeof(uint8_t), usart_rx_data); + osQInit(&usart_tx_q, sizeof(uint8_t), usart_tx_data); +} + +void USART2_IRQHandler(void) +{ + /* USART2 receive buffer contains a char. */ + if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET) + { + uint8_t data; + data = USART_ReceiveData(USART2) & 0xFF; + if(!osEnqueue(&usart_rx_q, (void*)&data)) + asm("NOP"); + // TODO: Throw receive buffer overflow error here + } + + /* USART2 transmit buffer empty. */ + if(USART_GetITStatus(USART2, USART_IT_TXE) == SET) + { + uint8_t data; + if(osDequeue(&usart_tx_q, &data)) + USART_SendData(USART2, data); + else + { + /* Nothing to send. Disable interrupt. */ + USART_ITConfig(USART2, USART_IT_TXE, DISABLE); + } + } +} + +static uint8_t usart2PutChar(uint8_t data) +{ + /* Put data in the q. */ + if(!osEnqueue(&usart_tx_q, (void*)&data)) + return 0; + /* Enable interrupt. */ + USART_ITConfig(USART2, USART_IT_TXE, ENABLE); + return 1; +} + +static uint8_t usart2GetChar(void) +{ + uint8_t data; + /* Wait until data arrives. */ + while(!osDequeue(&usart_rx_q, &data)){} + return data; +} + +uint8_t usart2PutString(uint8_t* word, size_t size) +{ + uint8_t j = 0; + /* Push data as long as it needs that it comes through. */ + for(uint8_t i=0; i 1) + asm("NOP"); + // TODO: Throw send buffer overflow error here + } + return 1; +} + +uint8_t usart2GetString(uint8_t* word, size_t buff_size, size_t *string_size) +{ + uint8_t data; + *string_size = 0; + do + { + data = usart2GetChar(); + if(data == 0) + return 0; + usart2PutChar(data); + if( *string_size < (buff_size-1) ) + word[*string_size] = data; + else + return 0; + // TODO: Throw buffer overflow error. + (*string_size)++; + } while( (data != '\r') && (data != '\n') ); + /* Append string termination. */ + word[*string_size] = '\0'; + (*string_size)++; + return 1; +} diff --git a/software/platform/usart.h b/software/platform/usart.h new file mode 100644 index 0000000..5174b14 --- /dev/null +++ b/software/platform/usart.h @@ -0,0 +1,18 @@ +/* + * usart.h + * + * Created on: Dec 6, 2017 + * Author: maximilian + */ + +#ifndef PLATFORM_USART_H_ +#define PLATFORM_USART_H_ + +#include "stm32f10x.h" +#include + +void usart2Init(void); +uint8_t usart2PutString(uint8_t* word, size_t size); +uint8_t usart2GetString(uint8_t* word, size_t buff_size, size_t *string_size); + +#endif /* PLATFORM_USART_H_ */