Maximilian Stiefel
7 years ago
7 changed files with 349 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,72 @@ |
|||
/*
|
|||
* queues.c |
|||
* |
|||
* Created on: Dec 6, 2017 |
|||
* Author: maximilian |
|||
*/ |
|||
|
|||
#include "stdlib.h" |
|||
#include "stm32f10x.h" |
|||
#include "queues.h" |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
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; |
|||
} |
@ -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 <stdlib.h> |
|||
|
|||
#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_ */ |
@ -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++; |
|||
} |
@ -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_ */ |
@ -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<size; i++) |
|||
while(!usart2PutChar(word[i])) |
|||
{ |
|||
j++; |
|||
if(j > 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; |
|||
} |
@ -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 <stdlib.h> |
|||
|
|||
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_ */ |
Loading…
Reference in new issue