add GPS (not ready)

This commit is contained in:
eddyem 2015-07-29 23:47:31 +03:00
parent 7e78a70aa5
commit d98cf154e5
28 changed files with 2117 additions and 0 deletions

BIN
GPS/GPS.bin Executable file

Binary file not shown.

228
GPS/GPS.c Normal file
View File

@ -0,0 +1,228 @@
/*
* GPS.c
*
* Copyright 2015 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 "GPS.h"
#include "uart.h"
#define GPS_endline() do{GPS_send_string((uint8_t*)"\r\n");}while(0)
#define U(arg) ((uint8_t*)arg)
void GPS_send_string(uint8_t *str){
while(*str)
fill_uart_buff(USART2, *str++);
}
int strncmp(const uint8_t *one, const uint8_t *two, int n){
int diff = 0;
do{
diff = (int)(*one++) - (int)(*two++);
}while(--n && diff == 0);
return diff;
}
uint8_t *ustrchr(uint8_t *str, uint8_t symbol){
// uint8_t *ptr = str;
do{
if(*str == symbol) return str;
}while(*(++str));
return NULL;
}
/*
// Check checksum
int checksum(uint8_t *buf){
uint8_t *eol;
char chs[3];
uint8_t checksum = 0;
if(*buf != '$' || !(eol = (uint8_t*)ustrchr((char*)buf, '*'))){
DBG("Wrong data: %s\n", buf);
return 0;
}
while(++buf != eol)
checksum ^= *buf;
snprintf(chs, 3, "%02X", checksum);
if(strncmp(chs, (char*)++buf, 2)){
DBG("Wrong checksum: %s", chs);
return 0;
}
return 1;
}*/
void send_chksum(uint8_t chs){
void puts(uint8_t c){
if(c < 10)
fill_uart_buff(USART2, c + '0');
else
fill_uart_buff(USART2, c + 'A' - 10);
}
puts(chs >> 4);
puts(chs & 0x0f);
}
/**
* Calculate checksum & write message to port
* @param buf - command to write (with leading $ and trailing *)
* return 0 if fails
*/
void write_with_checksum(uint8_t *buf){
uint8_t checksum = 0;
GPS_send_string(buf);
++buf; // skip leaders
do{
checksum ^= *buf++;
}while(*buf && *buf != '*');
send_chksum(checksum);
GPS_endline();
}
/**
* set rate for given NMEA field
* @param field - name of NMEA field
* @param rate - rate in seconds (0 disables field)
* @return -1 if fails, rate if OK
*/
void block_field(const uint8_t *field){
uint8_t buf[22];
memcpy(buf, U("$PUBX,40,"), 9);
memcpy(buf+9, field, 3);
memcpy(buf+12, U(",0,0,0,0*"), 9);
buf[21] = 0;
write_with_checksum(buf);
}
/**
* Send starting sequences (get only RMC messages)
*/
void GPS_send_start_seq(){
const uint8_t *GPmsgs[5] = {U("GSV"), U("GSA"), U("GGA"), U("GLL"), U("VTG")};
int i;
for(i = 0; i < 5; ++i)
block_field(GPmsgs[i]);
}
/*
uint8_t *nextpos(uint8_t **buf, int pos){
int i;
if(pos < 1) pos = 1;
for(i = 0; i < pos; ++i){
*buf = ustrchr(*buf, ',');
if(!*buf) break;
++(*buf);
}
return *buf;
}
#define NEXT() do{if(!nextpos(&buf, 1)) goto ret;}while(0)
#define SKIP(NPOS) do{if(!nextpos(&buf, NPOS)) goto ret;}while(0)
*/
/**
* Parse answer from GPS module
*/
void GPS_parse_answer(uint8_t *buf){
uint8_t *ptr;
DBG(buf);
if(strncmp(buf+3, U("RMC"), 3)) return; // not RMC message
buf += 7; // skip header
P("time: ");
if(*buf != ','){
ptr = ustrchr(buf, ',');
*ptr++ = 0;
P(buf);
buf = ptr;
P(" ");
}else{
P("undefined ");
++buf;
}
P("\n");
}
/*
void rmc(uint8_t *buf){
//DBG("rmc: %s\n", buf);
int H, M, LO, LA, d, m, y, getdate = 0;
double S, longitude, lattitude, speed, track, mag;
char varn = 'V', north = '0', east = '0', mageast = '0', mode = 'N';
sscanf((char*)buf, "%2d%2d%lf", &H, &M, &S);
NEXT();
if(*buf != ',') varn = *buf;
if(varn != 'A')
PRINT("(data could be wrong)");
else{
PRINT("(data valid)");
if(GP->date) getdate = 1; // as only we have valid data we show it to user
}
PRINT(" time: %02d:%02d:%05.2f", H, M, S);
PRINT(" timediff: %g", timediff(H, M, S));
NEXT();
sscanf((char*)buf, "%2d%lf", &LA, &lattitude);
NEXT();
if(*buf != ','){
north = *buf;
lattitude = (double)LA + lattitude / 60.;
if(north == 'S') lattitude = -lattitude;
PRINT(" latt: %g", lattitude);
Latt_mean += lattitude;
Latt_sq += lattitude*lattitude;
++Latt_N;
}
NEXT();
sscanf((char*)buf, "%3d%lf", &LO, &longitude);
NEXT();
if(*buf != ','){
east = *buf;
longitude = (double)LO + longitude / 60.;
if(east == 'W') longitude = -longitude;
PRINT(" long: %g", longitude);
Long_mean += longitude;
Long_sq += longitude*longitude;
++Long_N;
}
NEXT();
if(*buf != ','){
sscanf((char*)buf, "%lf", &speed);
PRINT(" speed: %gknots", speed);
}
NEXT();
if(*buf != ','){
sscanf((char*)buf, "%lf", &track);
PRINT(" track: %gdeg,True", track);
}
NEXT();
if(sscanf((char*)buf, "%2d%2d%2d", &d, &m, &y) == 3)
PRINT(" date(dd/mm/yy): %02d/%02d/%02d", d, m, y);
if(getdate) show_date(H,M,S,d,m,y); // show date & exit
NEXT();
sscanf((char*)buf, "%lf,%c", &mag, &mageast);
if(mageast == 'E' || mageast == 'W'){
if(mageast == 'W') mag = -mag;
PRINT(" magnetic var: %g", mag);
}
SKIP(2);
if(*buf != ','){
mode = *buf;
PRINT(" mode: %c", mode);
}
ret:
PRINT("\n");
}
*/

36
GPS/GPS.geany Normal file
View File

@ -0,0 +1,36 @@
[file_prefs]
final_new_line=true
ensure_convert_new_lines=true
strip_trailing_spaces=true
replace_tabs=false
[indentation]
indent_width=4
indent_type=1
indent_hard_tab_width=4
detect_indent=false
detect_indent_width=false
indent_mode=3
[project]
name=GPS
base_path=/home/eddy/Docs/SAO/ELECTRONICS/STM32/c8t6/GPS/
[long line marker]
long_line_behaviour=1
long_line_column=80
[files]
current_page=1
FILE_NAME_0=4732;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fuser_proto.c;0;4
FILE_NAME_1=0;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fuser_proto.h;0;4
FILE_NAME_2=6683;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fuart.c;0;4
FILE_NAME_3=1297;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fuart.h;0;4
FILE_NAME_4=2072;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fmain.c;0;4
FILE_NAME_5=1364;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fmain.h;0;4
FILE_NAME_6=949;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2FGPS.c;0;4
FILE_NAME_7=903;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2FGPS.h;0;4
FILE_NAME_8=2128;C;0;EUTF-8;1;1;0;%2Fhome%2Feddy%2FDocs%2FSAO%2FELECTRONICS%2FSTM32%2Fc8t6%2FGPS%2Fhardware_ini.c;0;4
[VTE]
last_dir=/home/eddy/Docs/SAO/Cameras/FLI_camera/my/Mytakepic

29
GPS/GPS.h Normal file
View File

@ -0,0 +1,29 @@
/*
* GPS.h
*
* Copyright 2015 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 __GPS_H__
#define __GPS_H__
void GPS_parse_answer(uint8_t *string);
void GPS_send_start_seq();
#endif // __GPS_H__

133
GPS/Makefile Normal file
View File

@ -0,0 +1,133 @@
BINARY = GPS
BOOTPORT ?= /dev/ttyUSB0
BOOTSPEED ?= 115200
# change this linking script depending on particular MCU model,
# for example, if you have STM32F103VBT6, you should write:
LDSCRIPT = ld/stm32f103x8.ld
LIBNAME = opencm3_stm32f1
DEFS = -DSTM32F1 -DEBUG
OBJDIR = mk
INDEPENDENT_HEADERS=
FP_FLAGS ?= -msoft-float
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
###############################################################################
# Executables
PREFIX ?= arm-none-eabi
RM := rm -f
RMDIR := rmdir
CC := $(PREFIX)-gcc
LD := $(PREFIX)-gcc
AR := $(PREFIX)-ar
AS := $(PREFIX)-as
OBJCOPY := $(PREFIX)-objcopy
OBJDUMP := $(PREFIX)-objdump
GDB := $(PREFIX)-gdb
STFLASH = $(shell which st-flash)
STBOOT = $(shell which stm32flash)
###############################################################################
# Source files
LDSCRIPT ?= $(BINARY).ld
SRC = $(wildcard *.c)
OBJS = $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
ifeq ($(strip $(OPENCM3_DIR)),)
OPENCM3_DIR := /usr/local/arm-none-eabi
$(info Using $(OPENCM3_DIR) path to library)
endif
INCLUDE_DIR = $(OPENCM3_DIR)/include
LIB_DIR = $(OPENCM3_DIR)/lib
SCRIPT_DIR = $(OPENCM3_DIR)/scripts
###############################################################################
# C flags
CFLAGS += -Os -g
CFLAGS += -Wall -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls
# -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -fno-common -ffunction-sections -fdata-sections
###############################################################################
# C & C++ preprocessor common flags
CPPFLAGS += -MD
CPPFLAGS += -Wall -Werror
CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
###############################################################################
# Linker flags
LDFLAGS += --static -nostartfiles
LDFLAGS += -L$(LIB_DIR)
LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += -Wl,-Map=$(*).map
LDFLAGS += -Wl,--gc-sections
###############################################################################
# Used libraries
LDLIBS += -l$(LIBNAME)
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
.SUFFIXES: .elf .bin .hex .srec .list .map .images
.SECONDEXPANSION:
.SECONDARY:
ELF := $(OBJDIR)/$(BINARY).elf
LIST := $(OBJDIR)/$(BINARY).list
BIN := $(BINARY).bin
HEX := $(BINARY).hex
all: bin
elf: $(ELF)
bin: $(BIN)
hex: $(HEX)
list: $(LIST)
$(OBJDIR):
mkdir $(OBJDIR)
$(OBJDIR)/%.o: %.c
@printf " CC $<\n"
$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $@ -c $<
$(SRC) : %.c : %.h $(INDEPENDENT_HEADERS)
@touch $@
%.h: ;
$(BIN): $(ELF)
@printf " OBJCOPY $(BIN)\n"
$(OBJCOPY) -Obinary $(ELF) $(BIN)
$(HEX): $(ELF)
@printf " OBJCOPY $(HEX)\n"
$(OBJCOPY) -Oihex $(ELF) $(HEX)
$(LIST): $(ELF)
@printf " OBJDUMP $(LIST)\n"
$(OBJDUMP) -S $(ELF) > $(LIST)
$(ELF): $(OBJDIR) $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
@printf " LD $(ELF)\n"
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
clean:
@printf " CLEAN\n"
$(RM) $(OBJS) $(OBJDIR)/*.d $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
$(RMDIR) $(OBJDIR)
flash: $(BIN)
@printf " FLASH $(BIN)\n"
$(STFLASH) write $(BIN) 0x8000000
boot: $(BIN)
@printf " LOAD $(BIN) through bootloader\n"
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
.PHONY: clean elf hex list flash boot
#-include $(OBJS:.o=.d)

8
GPS/README Normal file
View File

@ -0,0 +1,8 @@
NOT READY!
GPS RTC
written for chinese devboard based on STM32F103RBT6
Press H for help

314
GPS/cdcacm.c Normal file
View File

@ -0,0 +1,314 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright 2014 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cdcacm.h"
#include "user_proto.h"
#include "main.h"
// Buffer for USB Tx
static uint8_t USB_Tx_Buffer[USB_TX_DATA_SIZE];
static uint8_t USB_Tx_ptr = 0;
// connection flag
uint8_t USB_connected = 0;
static const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
.bDeviceClass = USB_CLASS_CDC,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = 0x0483,
.idProduct = 0x5740,
.bcdDevice = 0x0200,
.iManufacturer = 1,
.iProduct = 2,
.iSerialNumber = 3,
.bNumConfigurations = 1,
};
char usbdatabuf[USB_RX_DATA_SIZE]; // buffer for received data
int usbdatalen = 0; // lenght of received 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.
*/
static const struct usb_endpoint_descriptor comm_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x83,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16,
.bInterval = 255,
}};
static const struct usb_endpoint_descriptor data_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x01,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
}, {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x82,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64,
.bInterval = 1,
}};
static const struct {
struct usb_cdc_header_descriptor header;
struct usb_cdc_call_management_descriptor call_mgmt;
struct usb_cdc_acm_descriptor acm;
struct usb_cdc_union_descriptor cdc_union;
} __attribute__((packed)) cdcacm_functional_descriptors = {
.header = {
.bFunctionLength = sizeof(struct usb_cdc_header_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_HEADER,
.bcdCDC = 0x0110,
},
.call_mgmt = {
.bFunctionLength =
sizeof(struct usb_cdc_call_management_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0,
.bDataInterface = 1,
},
.acm = {
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_ACM,
.bmCapabilities = 0,
},
.cdc_union = {
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
.bControlInterface = 0,
.bSubordinateInterface0 = 1,
},
};
static const struct usb_interface_descriptor comm_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_CDC,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
.iInterface = 0,
.endpoint = comm_endp,
.extra = &cdcacm_functional_descriptors,
.extralen = sizeof(cdcacm_functional_descriptors),
}};
static const struct usb_interface_descriptor data_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0,
.endpoint = data_endp,
}};
static const struct usb_interface ifaces[] = {{
.num_altsetting = 1,
.altsetting = comm_iface,
}, {
.num_altsetting = 1,
.altsetting = data_iface,
}};
static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
.bNumInterfaces = 2,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
.bMaxPower = 0x32,
.interface = ifaces,
};
static const char *usb_strings[] = {
"Organisation, author",
"device",
"version",
};
// default line coding: B115200, 1stop, 8bits, parity none
struct usb_cdc_line_coding linecoding = {
.dwDTERate = 115200,
.bCharFormat = USB_CDC_1_STOP_BITS,
.bParityType = USB_CDC_NO_PARITY,
.bDataBits = 8,
};
/* Buffer to be used for control requests. */
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,
uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req)){
(void)complete;
(void)buf;
(void)usbd_dev;
char local_buf[10];
struct usb_cdc_line_coding lc;
switch (req->bRequest) {
case SET_CONTROL_LINE_STATE:{
if(req->wValue){ // terminal is opened
USB_connected = 1;
}else{ // terminal is closed
USB_connected = 0;
}
/*
* This Linux cdc_acm driver requires this to be implemented
* even though it's optional in the CDC spec, and we don't
* advertise it in the ACM functional descriptor.
*/
struct usb_cdc_notification *notif = (void *)local_buf;
/* We echo signals back to host as notification. */
notif->bmRequestType = 0xA1;
notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE;
notif->wValue = 0;
notif->wIndex = 0;
notif->wLength = 2;
local_buf[8] = req->wValue & 3;
local_buf[9] = 0;
usbd_ep_write_packet(usbd_dev, 0x83, local_buf, 10);
}break;
case SET_LINE_CODING:
if (!len || (*len != sizeof(struct usb_cdc_line_coding)))
return 0;
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;
case GET_LINE_CODING: // return linecoding buffer
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));
break;
default:
return 0;
}
return 1;
}
static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep){
(void)ep;
int len = usbd_ep_read_packet(usbd_dev, 0x01, usbdatabuf + usbdatalen, USB_RX_DATA_SIZE - usbdatalen);
usbdatalen += len;
if(usbdatalen >= USB_RX_DATA_SIZE){ // buffer overflow - drop all its contents
usbdatalen = 0;
}
}
static void cdcacm_data_tx_cb(usbd_device *usbd_dev, uint8_t ep){
(void)ep;
(void)usbd_dev;
usb_send_buffer();
}
static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue)
{
(void)wValue;
(void)usbd_dev;
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, USB_RX_DATA_SIZE, cdcacm_data_rx_cb);
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, USB_TX_DATA_SIZE, cdcacm_data_tx_cb);
usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
cdcacm_control_request);
}
static usbd_device *current_usb = NULL;
usbd_device *USB_init(){
current_usb = usbd_init(&stm32f103_usb_driver, &dev, &config,
usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
if(!current_usb) return NULL;
usbd_register_set_config_callback(current_usb, cdcacm_set_config);
return current_usb;
}
mutex_t send_block_mutex = MUTEX_UNLOCKED;
/**
* Put byte into USB buffer to send
* @param byte - a byte to put into a buffer
*/
void usb_send(uint8_t byte){
mutex_lock(&send_block_mutex);
USB_Tx_Buffer[USB_Tx_ptr++] = byte;
mutex_unlock(&send_block_mutex);
if(USB_Tx_ptr == USB_TX_DATA_SIZE){ // buffer can be overflowed - send it!
usb_send_buffer();
}
}
/**
* Send all data in buffer over USB
* this function runs when buffer is full or on SysTick
*/
void usb_send_buffer(){
if(MUTEX_LOCKED == mutex_trylock(&send_block_mutex)) return;
if(USB_Tx_ptr){
if(current_usb && USB_connected){
// usbd_ep_write_packet return 0 if previous packet isn't transmit yet
while(USB_Tx_ptr != usbd_ep_write_packet(current_usb, 0x82, USB_Tx_Buffer, USB_Tx_ptr));
usbd_poll(current_usb);
}
USB_Tx_ptr = 0;
}
mutex_unlock(&send_block_mutex);
}

54
GPS/cdcacm.h Normal file
View File

@ -0,0 +1,54 @@
/*
* ccdcacm.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 __CCDCACM_H__
#define __CCDCACM_H__
#include <libopencm3/usb/usbd.h>
// commands through EP0
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_RESPONSE 0x01
#define SET_COMM_FEATURE 0x02
#define GET_COMM_FEATURE 0x03
#define CLEAR_COMM_FEATURE 0x04
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define SEND_BREAK 0x23
// Size of input/output buffers
#define USB_TX_DATA_SIZE 64
#define USB_RX_DATA_SIZE 64
// USB connection flag
extern uint8_t USB_connected;
extern struct usb_cdc_line_coding linecoding;
extern char usbdatabuf[];
extern int usbdatalen;
usbd_device *USB_init();
void usb_send(uint8_t byte);
void usb_send_buffer();
#endif // __CCDCACM_H__

96
GPS/hardware_ini.c Normal file
View File

@ -0,0 +1,96 @@
/*
* 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.
*/
/*
* All hardware-dependent initialisation & definition should be placed here
* and in hardware_ini.h
*
*/
#include "main.h"
#include "hardware_ini.h"
/**
* GPIO initialisaion: clocking + pins setup
*/
void GPIO_init(){
/* rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN |
RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN |
RCC_APB2ENR_IOPEEN);
// Buttons: pull-up input
gpio_set_mode(BTNS_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN,
BTN_S2_PIN | BTN_S3_PIN);
// turn on pull-up
gpio_set(BTNS_PORT, BTN_S2_PIN | BTN_S3_PIN);
// LEDS: opendrain output
gpio_set_mode(LEDS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN,
LED_D1_PIN | LED_D2_PIN);
// turn off LEDs
gpio_set(LEDS_PORT, LED_D1_PIN | LED_D2_PIN);*/
/*
// USB_DISC: push-pull
gpio_set_mode(USB_DISC_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, USB_DISC_PIN);
// USB_POWER: open drain, externall pull down with R7 (22k)
gpio_set_mode(USB_POWER_PORT, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_FLOAT, USB_POWER_PIN);
*/
}
/*
* SysTick used for system timer with period of 1ms
*/
void SysTick_init(){
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); // Systyck: 72/8=9MHz
systick_set_reload(899); // 900 pulses: 10kHz
systick_interrupt_enable();
systick_counter_enable();
}
/*
// check buttons S2/S3
void check_btns(){
static uint8_t oldstate[2] = {1,1}; // old buttons state
uint8_t newstate[2], i;
static uint32_t Old_timer[2] = {0,0};
newstate[0] = gpio_get(BTNS_PORT, BTN_S2_PIN) ? 1 : 0;
newstate[1] = gpio_get(BTNS_PORT, BTN_S3_PIN) ? 1 : 0;
for(i = 0; i < 2; i++){
uint8_t new = newstate[i];
// pause for 60ms
uint32_t O = Old_timer[i];
if(O){
if(Timer - O > 60 || O > Timer){
P("Button S");
usb_send('2' + i);
if(new) P("released");
else P("pressed");
newline();
oldstate[i] = new;
Old_timer[i] = 0;
}
}
else if(new != oldstate[i]){
Old_timer[i] = Timer;
}
}
}
*/

76
GPS/hardware_ini.h Normal file
View File

@ -0,0 +1,76 @@
/*
* 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__
/*
* Timers:
* SysTick - system time
*/
void GPIO_init();
void SysTick_init();
/*
* Buttons on devboard
*/
#define BTNS_PORT GPIOC
// PCO -- S2
#define BTN_S2_PIN GPIO0
// PC1 -- S3
#define BTN_S3_PIN GPIO1
/*
* LEDS: PB9 for D1, PB8 for D2
*/
#define LEDS_PORT GPIOB
#define LED_D1_PIN GPIO9
#define LED_D2_PIN GPIO8
/*
* USB interface
* connect boot1 jumper to gnd, boot0 to gnd; and reconnect boot0 to +3.3 to boot flash
*/
/*
// USB_DICS (disconnect) - PC11
#define USB_DISC_PIN GPIO11
#define USB_DISC_PORT GPIOC
// USB_POWER (high level when USB connected to PC)
#define USB_POWER_PIN GPIO10
#define USB_POWER_PORT GPIOC
// change signal level on USB diconnect pin
#define usb_disc_high() gpio_set(USB_DISC_PORT, USB_DISC_PIN)
#define usb_disc_low() gpio_clear(USB_DISC_PORT, USB_DISC_PIN)
// in case of n-channel FET on 1.5k pull-up change on/off disconnect means low level
// in case of pnp bipolar transistor or p-channel FET on 1.5k pull-up disconnect means high level
#define usb_disconnect() usb_disc_high()
#define usb_connect() usb_disc_low()
*/
// my simple devboard have no variants for programmed connection/disconnection of USB
#define usb_disconnect()
#define usb_connect()
void check_btns();
#endif // __HARDWARE_INI_H__

9
GPS/ld/devices.data Normal file
View File

@ -0,0 +1,9 @@
stm32f103?4* stm32f1 ROM=16K RAM=6K
stm32f103?6* stm32f1 ROM=32K RAM=10K
stm32f103?8* stm32f1 ROM=64K RAM=20K
stm32f103?b* stm32f1 ROM=128K RAM=20K
stm32f103?c* stm32f1 ROM=256K RAM=48K
stm32f103?d* stm32f1 ROM=384K RAM=64K
stm32f103?e* stm32f1 ROM=512K RAM=64K
stm32f103?f* stm32f1 ROM=768K RAM=96K
stm32f103?g* stm32f1 ROM=1024K RAM=96K

31
GPS/ld/stm32f103x4.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103x6.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103x8.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xB.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xC.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xD.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xE.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xF.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 768K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

31
GPS/ld/stm32f103xG.ld Normal file
View File

@ -0,0 +1,31 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
}
/* Include the common ld script. */
INCLUDE libopencm3_stm32f1.ld

98
GPS/main.c Normal file
View File

@ -0,0 +1,98 @@
/*
* main.c
*
* 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"
#include "cdcacm.h"
#include "uart.h"
#include "GPS.h"
volatile uint32_t Ticks = 0; // global ticks (10kHz)
volatile uint32_t Timer = 0; // global timer (milliseconds)
usbd_device *usbd_dev;
int main(){
uint32_t usb_timer = 0;
uint8_t *string;
// RCC clocking: 8MHz oscillator -> 72MHz system
rcc_clock_setup_in_hse_8mhz_out_72mhz();
GPIO_init();
usb_disconnect(); // turn off USB while initializing all
// USB
usbd_dev = USB_init();
// SysTick is a system timer with 1ms period
SysTick_init();
UART_init(USART2); // init GPS UART
// wait a little and then turn on USB pullup
// for (i = 0; i < 0x800000; i++)
// __asm__("nop");
usb_connect(); // turn on USB
GPS_send_start_seq();
while(1){
usbd_poll(usbd_dev);
if(usbdatalen){ // there's something in USB buffer
usbdatalen = parce_incoming_buf(usbdatabuf, usbdatalen);
}
if((string = check_UART2()))
GPS_parse_answer(string);
if(Ticks - usb_timer > 9){ // 1ms cycle
usb_timer += 10;
//usb_send_buffer();
}else if(Ticks < usb_timer){ // Timer overflow
usb_timer = 0;
}
}
}
/**
* SysTick interrupt: increment global time & send data buffer through USB
*/
void sys_tick_handler(){
static int T = 0; // 0..10 - for millisecond timer
++Ticks;
if(++T == 10){
usb_send_buffer();
++Timer;
T = 0;
}
}
// pause function, delay in ms
void Delay(uint16_t _U_ time){
uint32_t waitto = Timer + time;
while(Timer < waitto);
}
/**
* print current time in milliseconds
*/
void print_time(){
print_int(Timer);
}

55
GPS/main.h Normal file
View File

@ -0,0 +1,55 @@
/*
* main.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 __MAIN_H__
#define __MAIN_H__
#include <stdlib.h>
#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/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/spi.h>
#define ADC_CHANNELS_NUMBER (10)
#include "sync.h" // mutexes
#include "user_proto.h"
extern void *memcpy(void *dest, const void *src, int n);
#define _U_ __attribute__((__unused__))
#define U8(x) ((uint8_t) x)
#define U16(x) ((uint16_t) x)
#define U32(x) ((uint32_t) x)
extern volatile uint32_t Timer; // global timer (milliseconds)
void Delay(uint16_t time);
#endif // __MAIN_H__

93
GPS/sync.c Normal file
View File

@ -0,0 +1,93 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* TODO:
* implement mutexes for other type of MCU (which doesn't have strex & ldrex)
*/
#include <libopencm3/cm3/sync.h>
/* DMB is supported on CM0 */
void __dmb()
{
__asm__ volatile ("dmb");
}
/* Those are defined only on CM3 or CM4 */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
uint32_t __ldrex(volatile uint32_t *addr)
{
uint32_t res;
__asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr));
return res;
}
uint32_t __strex(uint32_t val, volatile uint32_t *addr)
{
uint32_t res;
__asm__ volatile ("strex %0, %2, [%1]"
: "=&r" (res) : "r" (addr), "r" (val));
return res;
}
void mutex_lock(mutex_t *m)
{
uint32_t status = 0;
do {
/* Wait until the mutex is unlocked. */
while (__ldrex(m) != MUTEX_UNLOCKED);
/* Try to acquire it. */
status = __strex(MUTEX_LOCKED, m);
/* Did we get it? If not then try again. */
} while (status != 0);
/* Execute the mysterious Data Memory Barrier instruction! */
__dmb();
}
void mutex_unlock(mutex_t *m)
{
/* Ensure accesses to protected resource are finished */
__dmb();
/* Free the lock. */
*m = MUTEX_UNLOCKED;
}
/*
* Try to lock mutex
* if it's already locked or there was error in STREX, return MUTEX_LOCKED
* else return MUTEX_UNLOCKED
*/
mutex_t mutex_trylock(mutex_t *m){
uint32_t status = 0;
mutex_t old_lock = __ldrex(m); // get mutex value
// set mutex
status = __strex(MUTEX_LOCKED, m);
if(status == 0) __dmb();
else old_lock = MUTEX_LOCKED;
return old_lock;
}
#endif

53
GPS/sync.h Normal file
View File

@ -0,0 +1,53 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_CM3_SYNC_H
#define LIBOPENCM3_CM3_SYNC_H
void __dmb(void);
/* Implements synchronisation primitives as discussed in the ARM document
* DHT0008A (ID081709) "ARM Synchronization Primitives" and the ARM v7-M
* Architecture Reference Manual.
*/
/* --- Exclusive load and store instructions ------------------------------- */
/* Those are defined only on CM3 or CM4 */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
uint32_t __ldrex(volatile uint32_t *addr);
uint32_t __strex(uint32_t val, volatile uint32_t *addr);
/* --- Convenience functions ----------------------------------------------- */
/* Here we implement some simple synchronisation primitives. */
typedef uint32_t mutex_t;
#define MUTEX_UNLOCKED 0
#define MUTEX_LOCKED 1
void mutex_lock(mutex_t *m);
void mutex_unlock(mutex_t *m);
mutex_t mutex_trylock(mutex_t *m);
#endif
#endif

265
GPS/uart.c Normal file
View File

@ -0,0 +1,265 @@
/*
* 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"
#include "hardware_ini.h"
#include <string.h> // for memcpy
// Buffers for Tx
static UART_buff TX_buffer[2]; // Tx buffers for all three ports
static UART_buff RX_buffer[2]; // Rx buffers for all three ports
void fill_uart_RXbuff(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){
usart_set_baudrate(UART, 9600);
usart_set_databits(UART, 8);
usart_set_stopbits(UART, USART_STOPBITS_1);
usart_set_parity(UART, USART_PARITY_NONE);
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: // GPS UART
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;
RX_buffer[1].end = 0;
RX_buffer[1].start = 0;
// output pin setup
gpioport = GPIO_BANK_USART2_TX;
gpiopin = GPIO_USART2_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;
RX_buffer[0].end = 0;
RX_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); // GPIO pins
// 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);
// 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;
// Check if we were called because of RXNE
if(USART_SR(UART) & USART_SR_RXNE){
// parce incoming byte
data = usart_recv(UART);
fill_uart_RXbuff(UART, data);
}
// Check if we were called because of TXE -> send next byte in buffer
if((USART_CR1(UART) & USART_CR1_TXEIE) && (USART_SR(UART) & USART_SR_TXE)){
switch(UART){
case USART1:
bufidx = 0;
break;
case USART2:
bufidx = 1;
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_BUF_DATA_SIZE){ // reload start
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 interrupt handlers
void usart1_isr(){
UART_isr(USART1);
}
void usart2_isr(){
UART_isr(USART2);
}
// put byte into Tx buffer
void fill_uart_buff(uint32_t UART, uint8_t byte){
UART_buff *curbuff;
uint8_t bufidx = 0, endidx;
if(!(USART_CR1(UART) & USART_CR1_UE)) return; // UART disabled
USART_CR1(UART) &= ~USART_CR1_TXEIE; // disable TX interrupt while buffer filling
while ((USART_SR(UART) & USART_SR_TXE) == 0); // wait until last byte send
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_BUF_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_BUF_DATA_SIZE){ // end of buffer
if(bufidx != 0){ // no overflow
curbuff->end = 0;
goto end_of_fn;
}
}
// overflow: purge all data
bufidx = curbuff->start; // refresh data index
for(endidx = bufidx; endidx < UART_BUF_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);
}
/*
UART_buff *get_uart_buffer(uint32_t UART){
switch(UART){
case USART1:
return &RX_buffer[0];
break;
case USART2:
return &RX_buffer[1];
break;
default: // error - return
return NULL;
}
return NULL;
}*/
/**
* Check whether UART2 have a full text line
* @return string with data if data ready or NULL
*/
uint8_t *check_UART2(){
static int oldlen = 0;
static uint8_t buf[UART_BUF_DATA_SIZE+1];
UART_buff *curbuff = &RX_buffer[1];
uint8_t datalen = curbuff->end; // length of data in buffer - here we use param "end"
if(!datalen) return NULL; // buffer is empty
if(oldlen != datalen){
if(curbuff->buf[curbuff->end-1] != '\n'){ // string not full
oldlen = datalen;
return NULL;
}else{ // full string - copy it to buffer & clear indexes
memcpy(buf, curbuff->buf, datalen);
buf[datalen] = 0;
oldlen = curbuff->end = 0;
return buf;
}
}
return NULL;
}
/**
* Fill data in RX buffer to prepare it for further work
* we don't use "start" parameter here, it's 0 always
* @param UART - device to fill buffer
* @param byte - data byte
*/
void fill_uart_RXbuff(uint32_t UART, uint8_t byte){
UART_buff *curbuff;
uint8_t bufidx;
switch(UART){
case USART1:
bufidx = 0;
break;
case USART2:
bufidx = 1;
break;
default: // error - return
return;
}
curbuff = &RX_buffer[bufidx];
if(curbuff->end == UART_BUF_DATA_SIZE){ // end of buffer - forget about data
return;
}
curbuff->buf[curbuff->end++] = byte; // put byte into buffer
}

46
GPS/uart.h Normal file
View File

@ -0,0 +1,46 @@
/*
* 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_BUF_DATA_SIZE 128
typedef struct {
uint8_t buf[UART_BUF_DATA_SIZE];
uint8_t start; // index from where to start reading
uint8_t end; // index from where to start writing
} UART_buff;
void UART_init(uint32_t UART);
void UART_setspeed(uint32_t UART);
void fill_uart_buff(uint32_t UART, uint8_t byte);
void uart1_send(uint8_t byte);
void uart2_send(uint8_t byte);
uint8_t *check_UART2();
UART_buff *get_uart_buffer(uint32_t UART);
#endif // __UART_H__

198
GPS/user_proto.c Normal file
View File

@ -0,0 +1,198 @@
/*
* user_proto.c
*
* 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 "cdcacm.h"
#include "main.h"
#include "hardware_ini.h"
#include "GPS.h"
// integer value given by user
static volatile int32_t User_value = 0;
enum{
UVAL_START, // user start to write integer value
UVAL_ENTERED, // value entered but not printed
UVAL_BAD // entered bad value
};
uint8_t Uval_ready = UVAL_BAD;
int read_int(char *buf, int cnt);
intfun I = NULL; // function to process entered integer
#define READINT() do{i += read_int(&buf[i+1], len-i-1);}while(0)
void help(){
P("H\tshow this help\n");
// P("I\ttest entering integer value\n");
P("T\tshow current approx. time\n");
}
/**
* show entered integer value
*/
uint8_t show_int(int32_t v){
newline();
print_int(v);
newline();
return 0;
}
/**
* parce command buffer buf with length len
* return 0 if buffer processed or len if there's not enough data in buffer
*/
int parce_incoming_buf(char *buf, int len){
uint8_t command;
//uint32_t utmp;
int i = 0;
if(Uval_ready == UVAL_START){ // we are in process of user's value reading
i += read_int(buf, len);
}
if(Uval_ready == UVAL_ENTERED){
//print_int(User_value); // printout readed integer value for error control
Uval_ready = UVAL_BAD; // clear Uval
I(User_value);
return 0;
}
for(; i < len; i++){
command = buf[i];
if(!command) continue; // omit zero
switch (command){
case 'H': // show help
help();
break;
/* case 'I': // enter integer & show its value
I = show_int;
READINT();
break;*/
case 'T':
newline();
print_int(Timer); // be careful for Time >= 2^{31}!!!
newline();
break;
case '\n': // show newline, space and tab as is
case '\r':
case ' ':
case '\t':
break;
default:
command = '?'; // echo '?' on unknown command in byte mode
}
usb_send(command); // echo readed byte
}
return 0; // all data processed - 0 bytes leave in buffer
}
/**
* Send char array wrd thru USB or UART
*/
void prnt(uint8_t *wrd){
if(!wrd) return;
while(*wrd) usb_send(*wrd++);
}
/**
* Read from TTY integer value given by user (in DEC).
* Reading stops on first non-numeric symbol.
* To work with symbol terminals reading don't stops on buffer's end,
* it waits for first non-numeric char.
* When working on string terminals, terminate string by '\n', 0 or any other symbol
* @param buf - buffer to read from
* @param cnt - buffer length
* @return amount of readed symbols
*/
int read_int(char *buf, int cnt){
int readed = 0, i;
static int enteredDigits; // amount of entered digits
static int sign; // sign of readed value
if(Uval_ready){ // this is first run
Uval_ready = UVAL_START; // clear flag
enteredDigits = 0; // 0 digits entered
User_value = 0; // clear value
sign = 1; // clear sign
}
if(!cnt) return 0;
for(i = 0; i < cnt; i++, readed++){
uint8_t chr = buf[i];
if(chr == '-'){
if(enteredDigits == 0){ // sign should be first
sign = -1;
continue;
}else{ // '-' after number - reject entered value
Uval_ready = UVAL_BAD;
break;
}
}
if(chr < '0' || chr > '9'){
if(enteredDigits)
Uval_ready = UVAL_ENTERED;
else
Uval_ready = UVAL_BAD; // bad symbol
break;
}
User_value = User_value * 10 + (int32_t)(chr - '0');
enteredDigits++;
}
if(Uval_ready == UVAL_ENTERED) // reading has met an non-numeric character
User_value *= sign;
return readed;
}
/**
* Print buff as hex values
* @param buf - buffer to print
* @param l - buf length
* @param s - function to send a byte
*/
void print_hex(uint8_t *buff, uint8_t l){
void putc(uint8_t c){
if(c < 10)
usb_send(c + '0');
else
usb_send(c + 'a' - 10);
}
usb_send('0'); usb_send('x'); // prefix 0x
while(l--){
putc(buff[l] >> 4);
putc(buff[l] & 0x0f);
}
}
/**
* Print decimal integer value
* @param N - value to print
* @param s - function to send a byte
*/
void print_int(int32_t N){
uint8_t buf[10], L = 0;
if(N < 0){
usb_send('-');
N = -N;
}
if(N){
while(N){
buf[L++] = N % 10 + '0';
N /= 10;
}
while(L--) usb_send(buf[L]);
}else usb_send('0');
}

47
GPS/user_proto.h Normal file
View File

@ -0,0 +1,47 @@
/*
* user_proto.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 __USER_PROTO_H__
#define __USER_PROTO_H__
#include "cdcacm.h"
// shorthand for prnt
#define P(arg) do{prnt((uint8_t*)arg);}while(0)
// debug message - over USB
#ifdef EBUG
#define DBG(a) do{prnt((uint8_t*)a);}while(0)
#else
#define DBG(a)
#endif
typedef uint8_t (*intfun)(int32_t);
void prnt(uint8_t *wrd);
#define newline() usb_send('\n')
void print_int(int32_t N);
void print_hex(uint8_t *buff, uint8_t l);
int parce_incoming_buf(char *buf, int len);
#endif // __USER_PROTO_H__