mirror of
https://github.com/eddyem/IR-controller.git
synced 2025-12-06 10:45:15 +03:00
Added USART support (Up to three USARTs)
This commit is contained in:
parent
60fa061829
commit
7ebfa0fcb0
@ -20,11 +20,14 @@
|
|||||||
|
|
||||||
#include "cdcacm.h"
|
#include "cdcacm.h"
|
||||||
#include "user_proto.h"
|
#include "user_proto.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
// Buffer for USB Tx
|
// Buffer for USB Tx
|
||||||
static uint8_t USB_Tx_Buffer[USB_TX_DATA_SIZE];
|
static uint8_t USB_Tx_Buffer[USB_TX_DATA_SIZE];
|
||||||
static uint8_t USB_Tx_ptr = 0;
|
static uint8_t USB_Tx_ptr = 0;
|
||||||
|
// connection flag
|
||||||
|
uint8_t USB_connected = 0;
|
||||||
static const struct usb_device_descriptor dev = {
|
static const struct usb_device_descriptor dev = {
|
||||||
.bLength = USB_DT_DEVICE_SIZE,
|
.bLength = USB_DT_DEVICE_SIZE,
|
||||||
.bDescriptorType = USB_DT_DEVICE,
|
.bDescriptorType = USB_DT_DEVICE,
|
||||||
@ -176,6 +179,11 @@ struct usb_cdc_line_coding linecoding = {
|
|||||||
/* Buffer to be used for control requests. */
|
/* Buffer to be used for control requests. */
|
||||||
uint8_t usbd_control_buffer[128];
|
uint8_t usbd_control_buffer[128];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function runs every time it gets a request for control parameters get/set
|
||||||
|
* parameter SET_LINE_CODING used to change USART1 parameters: if you want to
|
||||||
|
* change them, just connect through USB with required parameters
|
||||||
|
*/
|
||||||
static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
|
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))
|
uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
|
||||||
{
|
{
|
||||||
@ -183,9 +191,20 @@ static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *
|
|||||||
(void)buf;
|
(void)buf;
|
||||||
(void)usbd_dev;
|
(void)usbd_dev;
|
||||||
char local_buf[10];
|
char local_buf[10];
|
||||||
|
struct usb_cdc_line_coding lc;
|
||||||
|
|
||||||
switch (req->bRequest) {
|
switch (req->bRequest) {
|
||||||
case SET_CONTROL_LINE_STATE:{
|
case SET_CONTROL_LINE_STATE:{
|
||||||
|
//P("SET_CONTROL_LINE_STATE\r\n", uart1_send);
|
||||||
|
//print_int(req->wValue, uart1_send);
|
||||||
|
//newline(uart1_send);
|
||||||
|
if(req->wValue){ // terminal is opened
|
||||||
|
USB_connected = 1;
|
||||||
|
//P("\r\n\tUSB connected!\r\n", uart1_send);
|
||||||
|
}else{ // terminal is closed
|
||||||
|
USB_connected = 0;
|
||||||
|
//P("\r\n\tUSB disconnected!\r\n", uart1_send);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* This Linux cdc_acm driver requires this to be implemented
|
* This Linux cdc_acm driver requires this to be implemented
|
||||||
* even though it's optional in the CDC spec, and we don't
|
* even though it's optional in the CDC spec, and we don't
|
||||||
@ -203,14 +222,28 @@ static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *
|
|||||||
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
|
||||||
}break;
|
}break;
|
||||||
case SET_LINE_CODING:
|
case SET_LINE_CODING:
|
||||||
if (*len != sizeof(struct usb_cdc_line_coding))
|
//P("SET_LINE_CODING, len=", uart1_send);
|
||||||
|
if (!len || (*len != sizeof(struct usb_cdc_line_coding)))
|
||||||
return 0;
|
return 0;
|
||||||
memcpy((void *)&linecoding, (void *)*buf, *len);
|
//print_int(*len, uart1_send);
|
||||||
|
//newline(uart1_send);
|
||||||
|
memcpy((void *)&lc, (void *)*buf, *len);
|
||||||
|
// Mark & Space parity don't support by hardware, check it
|
||||||
|
if(lc.bParityType == USB_CDC_MARK_PARITY || lc.bParityType == USB_CDC_SPACE_PARITY){
|
||||||
|
return 0; // error
|
||||||
|
}else{
|
||||||
|
memcpy((void *)&linecoding, (void *)&lc, sizeof(struct usb_cdc_line_coding));
|
||||||
|
UART_setspeed(USART1, &linecoding);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GET_LINE_CODING:
|
case GET_LINE_CODING: // return linecoding buffer
|
||||||
usbd_ep_write_packet(usbd_dev, 0x82, (char*)&linecoding, sizeof(linecoding));
|
if(len && *len == sizeof(struct usb_cdc_line_coding))
|
||||||
|
memcpy((void *)*buf, (void *)&linecoding, sizeof(struct usb_cdc_line_coding));
|
||||||
|
//usbd_ep_write_packet(usbd_dev, 0x83, (char*)&linecoding, sizeof(linecoding));
|
||||||
|
//P("GET_LINE_CODING\r\n", uart1_send);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
//P("UNKNOWN\r\n", uart1_send);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -218,10 +251,8 @@ static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *
|
|||||||
|
|
||||||
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep){
|
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep){
|
||||||
(void)ep;
|
(void)ep;
|
||||||
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
|
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
|
||||||
|
|
||||||
if(len > 0) parce_incoming_buf(buf, len, usb_send);
|
if(len > 0) parce_incoming_buf(buf, len, usb_send);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,12 +294,16 @@ usbd_device *USB_init(){
|
|||||||
* @param byte - a byte to put into a buffer
|
* @param byte - a byte to put into a buffer
|
||||||
*/
|
*/
|
||||||
void usb_send(uint8_t byte){
|
void usb_send(uint8_t byte){
|
||||||
if(!current_usb) return;
|
//if(!USB_connected) return;
|
||||||
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
|
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
|
||||||
if(USB_Tx_ptr == USB_TX_DATA_SIZE) // buffer can be overflowed - send it!
|
if(USB_Tx_ptr == USB_TX_DATA_SIZE) // buffer can be overflowed - send it!
|
||||||
usb_send_buffer();
|
usb_send_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send all data in buffer over USB
|
||||||
|
* this function runs when buffer is full or on SysTick
|
||||||
|
*/
|
||||||
void usb_send_buffer(){
|
void usb_send_buffer(){
|
||||||
if(USB_Tx_ptr){
|
if(USB_Tx_ptr){
|
||||||
if(current_usb)
|
if(current_usb)
|
||||||
|
|||||||
@ -23,12 +23,7 @@
|
|||||||
#ifndef __CCDCACM_H__
|
#ifndef __CCDCACM_H__
|
||||||
#define __CCDCACM_H__
|
#define __CCDCACM_H__
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h> // memcpy
|
|
||||||
#include <libopencm3/stm32/rcc.h>
|
|
||||||
#include <libopencm3/stm32/gpio.h>
|
|
||||||
#include <libopencm3/usb/usbd.h>
|
#include <libopencm3/usb/usbd.h>
|
||||||
#include <libopencm3/usb/cdc.h>
|
|
||||||
|
|
||||||
// commands through EP0
|
// commands through EP0
|
||||||
#define SEND_ENCAPSULATED_COMMAND 0x00
|
#define SEND_ENCAPSULATED_COMMAND 0x00
|
||||||
@ -44,6 +39,9 @@
|
|||||||
// Size of buffer to output
|
// Size of buffer to output
|
||||||
#define USB_TX_DATA_SIZE 64
|
#define USB_TX_DATA_SIZE 64
|
||||||
|
|
||||||
|
// USB connection flag
|
||||||
|
extern uint8_t USB_connected;
|
||||||
|
extern struct usb_cdc_line_coding linecoding;
|
||||||
|
|
||||||
usbd_device *USB_init();
|
usbd_device *USB_init();
|
||||||
void usb_send(uint8_t byte);
|
void usb_send(uint8_t byte);
|
||||||
|
|||||||
41
with_opencm3/hardware_ini.c
Normal file
41
with_opencm3/hardware_ini.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* hardware_ini.c - functions for HW initialisation
|
||||||
|
*
|
||||||
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "hardware_ini.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPIO initialisaion: clocking + ports setup
|
||||||
|
*/
|
||||||
|
void GPIO_init(){
|
||||||
|
rcc_periph_clock_enable(RCC_GPIOC);
|
||||||
|
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
|
||||||
|
GPIO_CNF_OUTPUT_PUSHPULL, GPIO11|GPIO12); // LED + USB
|
||||||
|
}
|
||||||
|
|
||||||
|
void SysTick_init(){
|
||||||
|
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
|
||||||
|
systick_set_reload(8999); // 9000 pulses: 1kHz
|
||||||
|
systick_interrupt_enable();
|
||||||
|
systick_counter_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
29
with_opencm3/hardware_ini.h
Normal file
29
with_opencm3/hardware_ini.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* hardware_ini.h
|
||||||
|
*
|
||||||
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef __HARDWARE_INI_H__
|
||||||
|
#define __HARDWARE_INI_H__
|
||||||
|
|
||||||
|
void GPIO_init();
|
||||||
|
void SysTick_init();
|
||||||
|
|
||||||
|
#endif // __HARDWARE_INI_H__
|
||||||
Binary file not shown.
@ -20,6 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "hardware_ini.h"
|
||||||
|
#include "cdcacm.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
uint32_t Timer = 0; // global timer (milliseconds)
|
uint32_t Timer = 0; // global timer (milliseconds)
|
||||||
|
|
||||||
@ -29,24 +32,27 @@ int main(){
|
|||||||
|
|
||||||
usbd_device *usbd_dev;
|
usbd_device *usbd_dev;
|
||||||
//rcc_clock_setup_in_hsi_out_48mhz();
|
//rcc_clock_setup_in_hsi_out_48mhz();
|
||||||
|
// RCC clocking: 8MHz oscillator -> 72MHz system
|
||||||
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
rcc_clock_setup_in_hse_8mhz_out_72mhz();
|
||||||
rcc_periph_clock_enable(RCC_GPIOC);
|
|
||||||
|
|
||||||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
|
// GPIO
|
||||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO11|GPIO12);
|
GPIO_init();
|
||||||
gpio_set(GPIOC, GPIO11); // turn off USB
|
gpio_set(GPIOC, GPIO11); // turn off USB
|
||||||
gpio_clear(GPIOC, GPIO12); // turn on LED
|
gpio_clear(GPIOC, GPIO12); // turn on LED
|
||||||
|
|
||||||
|
// init USART1
|
||||||
|
UART_init(USART1);
|
||||||
|
|
||||||
|
// USB
|
||||||
usbd_dev = USB_init();
|
usbd_dev = USB_init();
|
||||||
|
|
||||||
|
// wait a little and then turn on USB pullup
|
||||||
for (i = 0; i < 0x800000; i++)
|
for (i = 0; i < 0x800000; i++)
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
gpio_clear(GPIOC, GPIO11);
|
gpio_clear(GPIOC, GPIO11);
|
||||||
|
|
||||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
|
// SysTick is a system timer with 1mc period
|
||||||
systick_set_reload(8999); // 9000 pulses: 1kHz
|
SysTick_init();
|
||||||
systick_interrupt_enable();
|
|
||||||
systick_counter_enable();
|
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
usbd_poll(usbd_dev);
|
usbd_poll(usbd_dev);
|
||||||
@ -58,6 +64,9 @@ int main(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SysTick interrupt: increment global time & send data buffer through USB
|
||||||
|
*/
|
||||||
void sys_tick_handler(){
|
void sys_tick_handler(){
|
||||||
usb_send_buffer();
|
usb_send_buffer();
|
||||||
Timer++;
|
Timer++;
|
||||||
|
|||||||
@ -24,8 +24,16 @@
|
|||||||
#ifndef __MAIN_H__
|
#ifndef __MAIN_H__
|
||||||
#define __MAIN_H__
|
#define __MAIN_H__
|
||||||
|
|
||||||
#include "cdcacm.h"
|
#include <stdlib.h>
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
#include <libopencm3/stm32/gpio.h>
|
||||||
|
#include <libopencm3/stm32/usart.h>
|
||||||
|
#include <libopencm3/cm3/nvic.h>
|
||||||
|
#include <libopencm3/usb/cdc.h>
|
||||||
|
#include <libopencm3/usb/usbd.h>
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
|
#include <libopencm3/stm32/rcc.h>
|
||||||
|
|
||||||
#include "user_proto.h"
|
#include "user_proto.h"
|
||||||
|
|
||||||
#endif // __MAIN_H__
|
#endif // __MAIN_H__
|
||||||
|
|||||||
252
with_opencm3/uart.c
Normal file
252
with_opencm3/uart.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/*
|
||||||
|
* uart.c - functions to work with UART
|
||||||
|
*
|
||||||
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "cdcacm.h"
|
||||||
|
|
||||||
|
// Buffers for Tx
|
||||||
|
typedef struct {
|
||||||
|
uint8_t buf[UART_TX_DATA_SIZE];
|
||||||
|
uint8_t start; // index from where to start reading
|
||||||
|
uint8_t end; // index from where to start writing
|
||||||
|
} UART_buff;
|
||||||
|
static UART_buff TX_buffer[3]; // buffers for all three ports
|
||||||
|
|
||||||
|
void fill_uart_buff(uint32_t UART, uint8_t byte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set UART speed
|
||||||
|
* @param lc - UART parameters or NULL for value from cdcacm.c (started - B115200,8,N,1)
|
||||||
|
*/
|
||||||
|
void UART_setspeed(uint32_t UART, struct usb_cdc_line_coding *lc){
|
||||||
|
uint32_t tmp;
|
||||||
|
if(!lc) lc = &linecoding; // default linecoding from cdcacm.c
|
||||||
|
usart_set_baudrate(UART, lc->dwDTERate);
|
||||||
|
usart_set_databits(UART, lc->bDataBits);
|
||||||
|
switch(lc->bCharFormat){
|
||||||
|
case USB_CDC_1_5_STOP_BITS:
|
||||||
|
tmp = USART_STOPBITS_1_5;
|
||||||
|
break;
|
||||||
|
case USB_CDC_2_STOP_BITS:
|
||||||
|
tmp = USART_STOPBITS_2;
|
||||||
|
break;
|
||||||
|
case USB_CDC_1_STOP_BITS:
|
||||||
|
default:
|
||||||
|
tmp = USART_STOPBITS_1;
|
||||||
|
}
|
||||||
|
usart_set_stopbits(UART, tmp);
|
||||||
|
switch(lc->bParityType){
|
||||||
|
case USB_CDC_ODD_PARITY:
|
||||||
|
tmp = USART_PARITY_ODD;
|
||||||
|
break;
|
||||||
|
case USB_CDC_EVEN_PARITY:
|
||||||
|
tmp = USART_PARITY_EVEN;
|
||||||
|
break;
|
||||||
|
case USB_CDC_NO_PARITY:
|
||||||
|
default:
|
||||||
|
tmp = USART_PARITY_NONE;
|
||||||
|
}
|
||||||
|
usart_set_parity(UART, tmp);
|
||||||
|
usart_set_flow_control(UART, USART_FLOWCONTROL_NONE);
|
||||||
|
usart_set_mode(UART, USART_MODE_TX_RX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup UART
|
||||||
|
*/
|
||||||
|
void UART_init(uint32_t UART){
|
||||||
|
uint32_t irq, rcc, rccgpio, gpioport, gpiopin;
|
||||||
|
switch(UART){
|
||||||
|
case USART2:
|
||||||
|
irq = NVIC_USART2_IRQ; // interrupt for given USART
|
||||||
|
rcc = RCC_USART2; // RCC timing of USART
|
||||||
|
rccgpio = RCC_GPIOA; // RCC timing of GPIO pin (for output)
|
||||||
|
TX_buffer[1].end = 0; // reset counters
|
||||||
|
TX_buffer[1].start = 0;
|
||||||
|
// output pin setup
|
||||||
|
gpioport = GPIO_BANK_USART2_TX;
|
||||||
|
gpiopin = GPIO_USART2_TX;
|
||||||
|
break;
|
||||||
|
case USART3:
|
||||||
|
irq = NVIC_USART3_IRQ;
|
||||||
|
rcc = RCC_USART3;
|
||||||
|
rccgpio = RCC_GPIOB;
|
||||||
|
TX_buffer[2].end = 0;
|
||||||
|
TX_buffer[2].start = 0;
|
||||||
|
gpioport = GPIO_BANK_USART3_TX;
|
||||||
|
gpiopin = GPIO_USART3_TX;
|
||||||
|
break;
|
||||||
|
case USART1:
|
||||||
|
default:
|
||||||
|
irq = NVIC_USART1_IRQ;
|
||||||
|
rcc = RCC_USART1;
|
||||||
|
rccgpio = RCC_GPIOA;
|
||||||
|
TX_buffer[0].end = 0;
|
||||||
|
TX_buffer[0].start = 0;
|
||||||
|
gpioport = GPIO_BANK_USART1_TX;
|
||||||
|
gpiopin = GPIO_USART1_TX;
|
||||||
|
}
|
||||||
|
// enable clocking
|
||||||
|
rcc_periph_clock_enable(RCC_AFIO); // alternate functions
|
||||||
|
rcc_periph_clock_enable(rcc); // USART
|
||||||
|
rcc_periph_clock_enable(rccgpio); // output pin
|
||||||
|
// enable output pin
|
||||||
|
gpio_set_mode(gpioport, GPIO_MODE_OUTPUT_50_MHZ,
|
||||||
|
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, gpiopin);
|
||||||
|
// enable IRQ
|
||||||
|
nvic_enable_irq(irq);
|
||||||
|
UART_setspeed(UART, NULL);
|
||||||
|
// Enable UART receive interrupt
|
||||||
|
USART_CR1(UART) |= USART_CR1_RXNEIE;
|
||||||
|
// Enable UART
|
||||||
|
usart_enable(UART);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UART interrupts
|
||||||
|
*/
|
||||||
|
// common
|
||||||
|
void UART_isr(uint32_t UART){
|
||||||
|
uint8_t bufidx = 0, data;
|
||||||
|
UART_buff *curbuff;
|
||||||
|
sendfun sf = uart1_send;
|
||||||
|
// Check if we were called because of RXNE
|
||||||
|
if(USART_SR(UART) & USART_SR_RXNE){
|
||||||
|
// parce incoming byte
|
||||||
|
data = usart_recv(UART);
|
||||||
|
switch(UART){
|
||||||
|
case USART1:
|
||||||
|
sf = uart1_send;
|
||||||
|
break;
|
||||||
|
case USART2:
|
||||||
|
sf = uart2_send;
|
||||||
|
break;
|
||||||
|
case USART3:
|
||||||
|
sf = uart3_send;
|
||||||
|
break;
|
||||||
|
default: // error - return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parce_incoming_buf((char*)&data, 1, sf);
|
||||||
|
//fill_uart_buff(UART, data);
|
||||||
|
}
|
||||||
|
// Check if we were called because of TXE
|
||||||
|
if((USART_CR1(USART1) & USART_CR1_TXEIE) && (USART_SR(UART) & USART_SR_TXE)){
|
||||||
|
switch(UART){
|
||||||
|
case USART1:
|
||||||
|
bufidx = 0;
|
||||||
|
break;
|
||||||
|
case USART2:
|
||||||
|
bufidx = 1;
|
||||||
|
break;
|
||||||
|
case USART3:
|
||||||
|
bufidx = 2;
|
||||||
|
break;
|
||||||
|
default: // error - return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curbuff = &TX_buffer[bufidx];
|
||||||
|
bufidx = curbuff->start; // start of data in buffer
|
||||||
|
if(bufidx != curbuff->end){ // there's data in buffer
|
||||||
|
// Put data into the transmit register
|
||||||
|
usart_send(UART, curbuff->buf[bufidx]);
|
||||||
|
if(++(curbuff->start) == UART_TX_DATA_SIZE) // bufidx > endidx && got end of buffer
|
||||||
|
curbuff->start = 0;
|
||||||
|
}else{ // Disable the TXE interrupt, it's no longer needed
|
||||||
|
USART_CR1(UART) &= ~USART_CR1_TXEIE;
|
||||||
|
// empty indexes
|
||||||
|
curbuff->start = 0;
|
||||||
|
curbuff->end = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// particular
|
||||||
|
void usart1_isr(){
|
||||||
|
UART_isr(USART1);
|
||||||
|
}
|
||||||
|
void usart2_isr(){
|
||||||
|
UART_isr(USART2);
|
||||||
|
}
|
||||||
|
void usart3_isr(){
|
||||||
|
UART_isr(USART3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// put data into buffer
|
||||||
|
void fill_uart_buff(uint32_t UART, uint8_t byte){
|
||||||
|
UART_buff *curbuff;
|
||||||
|
uint8_t bufidx = 0, endidx;
|
||||||
|
switch(UART){
|
||||||
|
case USART1:
|
||||||
|
bufidx = 0;
|
||||||
|
break;
|
||||||
|
case USART2:
|
||||||
|
bufidx = 1;
|
||||||
|
break;
|
||||||
|
case USART3:
|
||||||
|
bufidx = 2;
|
||||||
|
break;
|
||||||
|
default: // error - return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curbuff = &TX_buffer[bufidx];
|
||||||
|
bufidx = curbuff->start; // start of data in buffer
|
||||||
|
endidx = curbuff->end; // end of data
|
||||||
|
curbuff->buf[endidx++] = byte; // put byte into buffer
|
||||||
|
// now check indexes
|
||||||
|
if(endidx != bufidx && endidx != UART_TX_DATA_SIZE){ // all OK - there's enough place for data
|
||||||
|
(curbuff->end)++; // just increment index in buffer
|
||||||
|
}else{ // dangerous situation: possible overflow
|
||||||
|
if(endidx == UART_TX_DATA_SIZE){ // end of buffer
|
||||||
|
if(bufidx != 0){ // no overflow
|
||||||
|
curbuff->end = 0;
|
||||||
|
goto end_of_fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// overflow: purge all data
|
||||||
|
USART_CR1(UART) &= ~USART_CR1_TXEIE; // disable TX interrupt - all will be done "by hands"
|
||||||
|
bufidx = curbuff->start; // refresh data index
|
||||||
|
for(endidx = bufidx; endidx < UART_TX_DATA_SIZE; endidx++) // first data porion
|
||||||
|
usart_send(UART, curbuff->buf[endidx]);
|
||||||
|
for(endidx = 0; endidx < bufidx; endidx++) // rest of data
|
||||||
|
usart_send(UART, curbuff->buf[endidx]);
|
||||||
|
curbuff->start = 0;
|
||||||
|
curbuff->end = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
end_of_fn:
|
||||||
|
// enable interrupts to send data from buffer
|
||||||
|
USART_CR1(UART) |= USART_CR1_TXEIE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* send data over UART - one function for each uart
|
||||||
|
* @param byte - one byte to put in UART queue
|
||||||
|
*/
|
||||||
|
void uart1_send(uint8_t byte){
|
||||||
|
fill_uart_buff(USART1, byte);
|
||||||
|
}
|
||||||
|
void uart2_send(uint8_t byte){
|
||||||
|
fill_uart_buff(USART2, byte);
|
||||||
|
}
|
||||||
|
void uart3_send(uint8_t byte){
|
||||||
|
fill_uart_buff(USART3, byte);
|
||||||
|
}
|
||||||
|
|
||||||
37
with_opencm3/uart.h
Normal file
37
with_opencm3/uart.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* uart.h
|
||||||
|
*
|
||||||
|
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef __UART_H__
|
||||||
|
#define __UART_H__
|
||||||
|
|
||||||
|
// Size of buffers
|
||||||
|
#define UART_TX_DATA_SIZE 64
|
||||||
|
|
||||||
|
void UART_init(uint32_t UART);
|
||||||
|
void UART_setspeed(uint32_t UART, struct usb_cdc_line_coding *linecoding);
|
||||||
|
|
||||||
|
void uart1_send(uint8_t byte);
|
||||||
|
void uart2_send(uint8_t byte);
|
||||||
|
void uart3_send(uint8_t byte);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __UART_H__
|
||||||
@ -20,7 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cdcacm.h"
|
#include "cdcacm.h"
|
||||||
#include "user_proto.h"
|
#include "main.h"
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
// integer value given by user
|
// integer value given by user
|
||||||
static volatile int32_t User_value = 0;
|
static volatile int32_t User_value = 0;
|
||||||
@ -46,15 +47,18 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
if(Uval_ready == UVAL_START){ // we are in process of user's value reading
|
if(Uval_ready == UVAL_START){ // we are in process of user's value reading
|
||||||
i += read_int(buf, len);
|
i += read_int(buf, len);
|
||||||
}else{
|
}
|
||||||
if(Uval_ready == UVAL_ENTERED){
|
if(Uval_ready == UVAL_ENTERED){
|
||||||
print_int(User_value, s); // printout readed integer value for error control
|
print_int(User_value, s); // printout readed integer value for error control
|
||||||
Uval_ready = UVAL_PRINTED;
|
Uval_ready = UVAL_PRINTED;
|
||||||
}
|
}
|
||||||
if(I && Uval_ready == UVAL_CHECKED) I(User_value, s);
|
if(I && Uval_ready == UVAL_CHECKED){
|
||||||
|
Uval_ready = UVAL_BAD; // clear Uval_ready
|
||||||
|
I(User_value, s);
|
||||||
}
|
}
|
||||||
for(; i < len; i++){
|
for(; i < len; i++){
|
||||||
command = buf[i];
|
command = buf[i];
|
||||||
|
if(!command) continue; // omit zero
|
||||||
switch (command){
|
switch (command){
|
||||||
case 'b': // turn LED off
|
case 'b': // turn LED off
|
||||||
gpio_set(GPIOC, GPIO12);
|
gpio_set(GPIOC, GPIO12);
|
||||||
@ -74,6 +78,20 @@ void parce_incoming_buf(char *buf, int len, sendfun s){
|
|||||||
if(Uval_ready == UVAL_PRINTED) Uval_ready = UVAL_BAD;
|
if(Uval_ready == UVAL_PRINTED) Uval_ready = UVAL_BAD;
|
||||||
else WRONG_COMMAND();
|
else WRONG_COMMAND();
|
||||||
break;
|
break;
|
||||||
|
case 'u': // check USB connection
|
||||||
|
P("\r\nUSB ", s);
|
||||||
|
if(!USB_connected) P("dis", s);
|
||||||
|
P("connected\r\n",s);
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case 'U': // test: init USART1
|
||||||
|
UART_init(USART1);
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case '\n': // show newline as is
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
WRONG_COMMAND(); // echo '?' on unknown command
|
WRONG_COMMAND(); // echo '?' on unknown command
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user