restructuring

This commit is contained in:
2022-03-10 11:04:14 +03:00
parent 29560b7c0c
commit 733dbd75d2
1758 changed files with 14 additions and 26855 deletions

View File

@@ -0,0 +1,133 @@
BINARY = onewire
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/stm32f103xB.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)

View File

@@ -0,0 +1,8 @@
My approach to semi-hardware 1-wire realisation based on DMA+TIM2
written for chinese devboard based on STM32F103RBT6
Press H for help
// Still some troubles left: for example, can't read ROM; also the code isn't fully done yet

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);
}

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__

View File

@@ -0,0 +1,98 @@
/*
* 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);
// test pin PC10: Push-Pull
#ifdef EBUG
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO10);
#endif
/*
// 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(8999); // 9000 pulses: 1kHz
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;
}
}
}

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__

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

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

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

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

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

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

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

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

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

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

View File

@@ -0,0 +1,92 @@
/*
* 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 "onewire.h"
volatile uint32_t Timer = 0; // global timer (milliseconds)
usbd_device *usbd_dev;
int main(){
uint32_t Old_timer = 0;
// 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();
// wait a little and then turn on USB pullup
// for (i = 0; i < 0x800000; i++)
// __asm__("nop");
usb_connect(); // turn on USB
init_ow_dmatimer();
while(1){
usbd_poll(usbd_dev);
if(usbdatalen){ // there's something in USB buffer
usbdatalen = parse_incoming_buf(usbdatabuf, usbdatalen);
}
//check_and_parse_UART(USART1); // also check data in UART buffers
check_btns();
if(Timer - Old_timer > 999){ // one-second cycle
Old_timer += 1000;
}else if(Timer < Old_timer){ // Timer overflow
Old_timer = 0;
}
OW_process();
}
}
/**
* SysTick interrupt: increment global time & send data buffer through USB
*/
void sys_tick_handler(){
Timer++;
usbd_poll(usbd_dev);
usb_send_buffer();
}
// pause function, delay in ms
void Delay(uint16_t _U_ time){
uint32_t waitto = Timer + time;
while(Timer < waitto);
}
/**
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
* with ' ' as delimeter
*/
void print_time(){
print_int(Timer);
}

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 <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/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/timer.h>
#define ADC_CHANNELS_NUMBER (10)
#include "sync.h" // mutexes
#include "user_proto.h"
#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__

Binary file not shown.

View File

@@ -0,0 +1,554 @@
/*
* onewire.c - functions to work with 1-wire devices
*
* 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 "onewire.h"
#include "user_proto.h"
OW_ID id_array[OW_MAX_NUM]; // 1-wire devices ID buffer (not more than eight)
uint8_t dev_amount = 0; // amount of 1-wire devices
// states of 1-wire processing queue
typedef enum{
OW_OFF_STATE, // not working
OW_RESET_STATE, // reset bus
OW_SEND_STATE, // send data
OW_READ_STATE, // wait for reading
} OW_States;
volatile OW_States OW_State = OW_OFF_STATE; // 1-wire state, 0-not runned
void (*ow_process_resdata)() = NULL;
void wait_reading();
uint16_t tim2_buff[TIM2_DMABUFF_SIZE];
uint16_t tim2_inbuff[TIM2_DMABUFF_SIZE];
int tum2buff_ctr = 0;
uint8_t ow_done = 1;
uint8_t ow_measurements_done = 0;
/**
* this function sends bits of ow_byte (LSB first) to 1-wire line
* @param ow_byte - byte to convert
* @param Nbits - number of bits to send
* @param ini - 1 to zero counter
*/
uint8_t OW_add_byte(uint8_t ow_byte){
uint8_t i, byte;
for(i = 0; i < 8; i++){
if(ow_byte & 0x01){
byte = BIT_ONE_P;
}else{
byte = BIT_ZERO_P;
}
if(tum2buff_ctr == TIM2_DMABUFF_SIZE){
ERR("Tim2 buffer overflow");
return 0; // avoid buffer overflow
}
tim2_buff[tum2buff_ctr++] = byte;
ow_byte >>= 1;
}
// INT(tum2buff_ctr);
// DBG(" bytes in send buffer\n");
return 1;
}
/**
* Adds Nbytes bytes 0xff for reading sequence
*/
uint8_t OW_add_read_seq(uint8_t Nbytes){
uint8_t i;
if(Nbytes == 0) return 0;
Nbytes *= 8; // 8 bits for each byte
for(i = 0; i < Nbytes; i++){
if(tum2buff_ctr == TIM2_DMABUFF_SIZE){
ERR("Tim2 buffer overflow");
return 0;
}
tim2_buff[tum2buff_ctr++] = BIT_READ_P;
}
// INT(tum2buff_ctr);
// DBG(" bytes in send buffer\n");
return 1;
}
/**
* Fill output buffer with data from 1-wire
* @param start_idx - index from which to start (byte number)
* @param N - data length (in **bytes**)
* @outbuf - where to place data
*/
void read_from_OWbuf(uint8_t start_idx, uint8_t N, uint8_t *outbuf){
start_idx *= 8;
uint8_t i, j, last = start_idx + N * 8, byte;
if(last >= TIM2_DMABUFF_SIZE) last = TIM2_DMABUFF_SIZE;
for(i = start_idx; i < last;){
byte = 0;
for(j = 0; j < 8; j++){
byte >>= 1;
// INT(tim2_inbuff[i]);
// DBG(" ");
if(tim2_inbuff[i++] < ONE_ZERO_BARRIER)
byte |= 0x80;
}
*outbuf++ = byte;
// DBG("readed \n");
}
// print_hex(outbuf-N, N);
// DBG(" readed\n");
}
// there's a mistake in opencm3, so redefine this if needed (TIM_CCMR2_CC3S_IN_TI1 -> TIM_CCMR2_CC3S_IN_TI4)
#ifndef TIM_CCMR2_CC3S_IN_TI4
#define TIM_CCMR2_CC3S_IN_TI4 (2)
#endif
void init_ow_dmatimer(){ // tim2_ch4 - PA3, no remap
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO3);
rcc_periph_clock_enable(RCC_TIM2);
rcc_periph_clock_enable(RCC_DMA1);
timer_reset(TIM2);
// timers have frequency of 1MHz -- 1us for one step
// 36MHz of APB1
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
// 72MHz div 72 = 1MHz
TIM2_PSC = 71; // prescaler is (div - 1)
TIM2_CR1 = TIM_CR1_ARPE; // bufferize ARR/CCR
TIM2_ARR = RESET_LEN;
// PWM_OUT: TIM2_CH4; capture: TIM2_CH3
// PWM edge-aligned mode & enable preload for CCR4, CC3 takes input from TI4
TIM2_CCMR2 = TIM_CCMR2_OC4M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_CC3S_IN_TI4;
TIM2_CCR4 = 0; // set output value to 1 by clearing CCR4
TIM2_EGR = TIM_EGR_UG; // update values of ARR & CCR4
// set low polarity for CC4, high for CC3 & enable CC4 out and CC3 in
TIM2_CCER = TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
// TIM2_CH4 - DMA1, channel 7
dma_channel_reset(DMA1, DMA_CHANNEL7);
DMA1_CCR7 = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
| DMA_CCR_TEIE | DMA_CCR_TCIE | DMA_CCR_PL_HIGH;
nvic_enable_irq(NVIC_DMA1_CHANNEL7_IRQ); // enable dma1_channel7_isr
tum2buff_ctr = 0;
DBG("OW INITED\n");
#ifdef EBUG
gpio_set(GPIOC, GPIO10);
#endif
}
void run_dmatimer(){
ow_done = 0;
TIM2_CR1 = 0;
adc_disable_dma(ADC1); // turn off DMA & ADC
adc_off(ADC1);
// TIM2_CH4 - DMA1, channel 7
DMA1_IFCR = DMA_ISR_TEIF7|DMA_ISR_HTIF7|DMA_ISR_TCIF7|DMA_ISR_GIF7 |
DMA_ISR_TEIF1|DMA_ISR_HTIF1|DMA_ISR_TCIF1|DMA_ISR_GIF1; // clear flags
DMA1_CCR7 &= ~DMA_CCR_EN; // disable (what if it's enabled?) to set address
DMA1_CPAR7 = (uint32_t) &(TIM_CCR4(TIM2)); // dma_set_peripheral_address(DMA1, DMA_CHANNEL7, (uint32_t) &(TIM_CCR4(TIM2)));
DMA1_CMAR7 = (uint32_t) &tim2_buff[1]; // dma_set_memory_address(DMA1, DMA_CHANNEL7, (uint32_t)tim2_buff);
DMA1_CNDTR7 = tum2buff_ctr-1;//dma_set_number_of_data(DMA1, DMA_CHANNEL7, tum2buff_ctr);
// TIM2_CH3 - DMA1, channel 1
dma_channel_reset(DMA1, DMA_CHANNEL1);
DMA1_CCR1 = DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
| DMA_CCR_TEIE | DMA_CCR_TCIE | DMA_CCR_PL_HIGH;
DMA1_CPAR1 = (uint32_t) &(TIM_CCR3(TIM2)); //dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t) &(TIM_CCR3(TIM2)));
DMA1_CMAR1 = (uint32_t) tim2_inbuff; //dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) tim2_inbuff);
DMA1_CNDTR1 = tum2buff_ctr; //dma_set_number_of_data(DMA1, DMA_CHANNEL1, tum2buff_ctr);
nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);
DMA1_CCR7 |= DMA_CCR_EN; //dma_enable_channel(DMA1, DMA_CHANNEL7);
DMA1_CCR1 |= DMA_CCR_EN; //dma_enable_channel(DMA1, DMA_CHANNEL1);
TIM2_SR = 0; // clear all flags
TIM2_ARR = BIT_LEN; // bit length
TIM2_CCR4 = tim2_buff[0]; // we should manually set first bit to avoid zero in tim2_inbuff[0]
TIM2_EGR = TIM_EGR_UG; // update value of ARR
TIM2_CR1 = TIM_CR1_ARPE; // bufferize ARR/CCR
TIM2_CR2 &= ~TIM_CR2_CCDS; // timer_set_dma_on_compare_event(TIM2);
TIM2_DIER = TIM_DIER_CC4DE | TIM_DIER_CC3DE; // enable DMA events
// set low polarity, enable cc out & enable input capture
TIM2_CR1 |= TIM_CR1_CEN; // run timer
#ifdef EBUG
gpio_clear(GPIOC, GPIO10);
#endif
/* DBG("RUN transfer of ");
INT(tum2buff_ctr);
DBG(" bits\n");*/
}
uint16_t rstat = 0, lastcc3 = 3;
void ow_reset(){
//init_ow_dmatimer();
ow_done = 0;
rstat = 0;
TIM2_SR = 0; // clear all flags
TIM2_CR1 = 0;
TIM2_DIER = 0; // disable timer interrupts
TIM2_ARR = RESET_LEN; // set period to 1ms
TIM2_CCR4 = RESET_P; // zero pulse length
TIM2_EGR = TIM_EGR_UG; // update values of ARR & CCR4
//TIM2_CCMR2 = TIM_CCMR2_OC4M_PWM1 | TIM_CCMR2_OC4PE | TIM_CCMR2_CC3S_IN_TI4;
//TIM2_CCER = TIM_CCER_CC4P | TIM_CCER_CC4E | TIM_CCER_CC3E;
// DBG("OW RESET in process");
TIM2_DIER = TIM_DIER_CC3IE;
#ifdef EBUG
gpio_clear(GPIOC, GPIO10);
#endif
TIM2_CR1 = TIM_CR1_OPM | TIM_CR1_CEN | TIM_CR1_UDIS; // we need only single pulse & run timer; disable UEV
TIM2_SR = 0; // clear update flag generated after timer's running
nvic_enable_irq(NVIC_TIM2_IRQ);
}
void tim2_isr(){
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
TIM2_DIER = 0; // disable all timer interrupts
#ifdef EBUG
gpio_set(GPIOC, GPIO10);
#endif
TIM2_CCR4 = 0; // set output value to 1
TIM2_SR = 0; // clear flag
nvic_disable_irq(NVIC_TIM2_IRQ);
ow_done = 1;
rstat = lastcc3;
// DBG(" ... done!\n");
}
if(TIM2_SR & TIM_SR_CC3IF){ // we need this interrupt to store CCR3 value
lastcc3 = TIM2_CCR3;
TIM2_CR1 &= ~TIM_CR1_UDIS; // enable UEV
TIM2_SR = 0; // clear flag (we've manage TIM_SR_UIF before, so can simply do =0)
TIM2_DIER |= TIM_DIER_UIE; // Now allow also Update interrupts to turn off everything
}
}
/**
* DMA interrupt in 1-wire mode
*/
void dma1_channel1_isr(){
// int i;
if(DMA1_ISR & DMA_ISR_TCIF1){
#ifdef EBUG
gpio_set(GPIOC, GPIO10);
#endif
DMA1_IFCR = DMA_IFCR_CTCIF1;
TIM2_CR1 &= ~TIM_CR1_CEN; // timer_disable_counter(TIM2);
DMA1_CCR1 &= ~DMA_CCR_EN; // disable DMA1 channel 1
nvic_disable_irq(NVIC_DMA1_CHANNEL1_IRQ);
ow_done = 1;
/* for(i = 0; i < tum2buff_ctr; i++){
print_int(tim2_inbuff[i]);
P(" ");
}
P("\n");*/
}else if(DMA1_ISR & DMA_ISR_TEIF1){
DMA1_IFCR = DMA_IFCR_CTEIF1;
DBG("DMA in transfer error\n");
}
}
void dma1_channel7_isr(){
if(DMA1_ISR & DMA_ISR_TCIF7){
DMA1_IFCR = DMA_IFCR_CTCIF7; // clear flag
DMA1_CCR7 &= ~DMA_CCR_EN; // disable DMA1 channel 7
}else if(DMA1_ISR & DMA_ISR_TEIF7){
DMA1_IFCR = DMA_IFCR_CTEIF7;
DBG("DMA out transfer error\n");
}
}
uint8_t OW_get_reset_status(){
if(rstat < RESET_BARRIER) return 0; // no devices
return 1;
}
uint8_t ow_data_ready = 0; // flag of reading OK
/**
* Process 1-wire commands depending on its state
*/
void OW_process(){
static uint8_t ow_was_reseting = 0;
switch(OW_State){
case OW_OFF_STATE:
return;
break;
case OW_RESET_STATE:
//DBG("OW reset\n");
OW_State = OW_SEND_STATE;
ow_was_reseting = 1;
ow_reset();
break;
case OW_SEND_STATE:
if(!ow_done) return; // reset in work
if(ow_was_reseting){
if(rstat < RESET_BARRIER){
ERR("Error: no 1-wire devices found");
INT(rstat);
DBG("\n");
ow_was_reseting = 0;
OW_State = OW_OFF_STATE;
return;
}
}
ow_was_reseting = 0;
OW_State = OW_READ_STATE;
run_dmatimer(); // turn on data transfer
//DBG("OW send\n");
break;
case OW_READ_STATE:
if(!ow_done) return; // data isn't ready
OW_State = OW_OFF_STATE;
// adc_dma_on(); // return DMA1_1 to ADC at end of data transmitting
if(ow_process_resdata)
ow_process_resdata();
ow_data_ready = 1;
//DBG("OW read\n");
break;
}
}
uint8_t *read_buf = NULL; // buffer for storing readed data
/**
* fill ID buffer with readed data
*/
void fill_buff_with_data(){
ow_process_resdata = NULL;
if(!read_buf) return;
read_from_OWbuf(1, 8, read_buf);
int i, j;
P("Readed ID: ");
for(i = 0; i < 8; ++i){
print_hex(&read_buf[i], 1);
usb_send(' ');
}
usb_send('\n');
// now check stored ROMs
for(i = 0; i < dev_amount; ++i){
uint8_t *ROM = id_array[i].bytes;
for(j = 0; j < 8; j++)
if(ROM[j] != read_buf[j]) break;
if(j == 8){ // we found this cell
DBG("Such ID exists\n");
goto ret;
}
}
++dev_amount;
ret:
read_buf = NULL;
}
/**
* fill Nth array with identificators
*/
//uint8_t comtosend = 0;
void OW_fill_next_ID(){
if(dev_amount >= OW_MAX_NUM){
ERR("No memory left for new device\n");
return;
}
ow_data_ready = 0;
OW_State = OW_RESET_STATE;
OW_reset_buffer();
OW_add_byte(OW_READ_ROM);
OW_add_read_seq(8); // wait for 8 bytes
read_buf = id_array[dev_amount].bytes;
ow_process_resdata = fill_buff_with_data;
DBG("wait for ID\n");
}
/**
* Procedure of 1-wire communications
* variables:
* @param sendReset - send RESET before transmission
* @param command - bytes sent to the bus (if we want to read, send OW_READ_SLOT)
* @param cLen - command buffer length (how many bytes to send)
* @return 1 if succeed, 0 if failure
*/
uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen){
ow_data_ready = 0;
// if reset needed - send RESET and check bus
if(sendReset)
OW_State = OW_RESET_STATE;
else
OW_State = OW_SEND_STATE;
OW_reset_buffer();
while(cLen-- > 0){
if(!OW_add_byte(*command++)) return 0;
}
return 1;
}
/**
* convert temperature from scratchpad
* in case of error return 200000 (ERR_TEMP_VAL)
* return value in 10th degrees centigrade
*
* 0 - themperature LSB
* 1 - themperature MSB (all higher bits are sign)
* 2 - T_H
* 3 - T_L
* 4 - B20: Configuration register (only bits 6/5 valid: 9..12 bits resolution); 0xff for S20
* 5 - 0xff (reserved)
* 6 - (reserved for B20); S20: COUNT_REMAIN (0x0c)
* 7 - COUNT PER DEGR (0x10)
* 8 - CRC
*/
int32_t gettemp(uint8_t *scratchpad){
// detect DS18S20
int32_t t = 0;
uint8_t l,m;
int8_t v;
if(scratchpad[7] == 0xff) // 0xff can be only if there's no such device or some other error
return ERR_TEMP_VAL;
m = scratchpad[1];
l = scratchpad[0];
if(scratchpad[4] == 0xff){ // DS18S20
v = l >> 1 | (m & 0x80); // take signum from MSB
t = ((int32_t)v) * 10L;
if(l&1) t += 5L; // decimal 0.5
}else{ // DS18B20
v = l>>4 | ((m & 7)<<4) | (m & 0x80);
t = ((int32_t)v) * 10L;
m = (l & 0x0f) >> 1; // add decimal
// 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 ->
// 0 1 1 2 3 3 4 4 5 6 6 7 8 8 9 9
t += (int32_t)m; // t = v*10 + l*0.625 -> convert
if(m) ++t; // 1->1, 2->3, 3->4, 4->5, 5->6
if(m > 5) ++t; // 6->8, 7->9
}
return t;
}
int32_t temperature = ERR_TEMP_VAL;
int8_t Ncur = 0;
/**
* get temperature from buffer
*/
void convert_next_temp(){
uint8_t scratchpad[9];
ow_process_resdata = NULL;
if(dev_amount < 2){
read_from_OWbuf(2, 9, scratchpad);
}else{
read_from_OWbuf(10, 9, scratchpad);
}
temperature = gettemp(scratchpad);
DBG("Readed temperature: ");
INT(temperature);
DBG("/10 degrC\n");
}
/**
* read next stored thermometer
*/
void OW_read_next_temp(){
ow_data_ready = 0;
OW_State = OW_RESET_STATE;
OW_reset_buffer();
int i;
if(dev_amount < 2){
Ncur = -1;
OW_add_byte(OW_SKIP_ROM);
}else{
if(++Ncur >= dev_amount) Ncur = 0;
OW_add_byte(OW_MATCH_ROM);
uint8_t *ROM = id_array[Ncur].bytes;
for(i = 0; i < 8; ++i)
OW_add_byte(ROM[i]);
}
OW_add_byte(OW_READ_SCRATCHPAD);
OW_add_read_seq(9); // wait for 9 bytes - ROM
ow_process_resdata = convert_next_temp;
}
void wait_reading(){
uint8_t bt;
read_from_OWbuf(0, 1, &bt);
if(bt == 0xff){ // the conversion is done!
ow_measurements_done = 1;
ow_process_resdata = NULL;
DBG("Measurements done!\n");
}else{
OW_State = OW_SEND_STATE;
OW_reset_buffer();
ow_data_ready = 0;
OW_add_read_seq(1); // send read seq waiting for end of conversion
}
}
void OW_send_read_seq(){
ow_data_ready = 0;
ow_measurements_done = 0;
OW_State = OW_RESET_STATE;
OW_reset_buffer();
OW_add_byte(OW_SKIP_ROM);
OW_add_byte(OW_CONVERT_T);
OW_add_read_seq(1); // send read seq waiting for end of conversion
ow_process_resdata = wait_reading;
}
/*
* scan 1-wire bus
* WARNING! The procedure works in real-time, so it is VERY LONG
* num - max number of devices
* buf - array for devices' ID's (8*num bytes)
* return amount of founded devices
*
uint8_t OW_Scan(uint8_t *buf, uint8_t num){
unsigned long path,next,pos;
uint8_t bit,chk;
uint8_t cnt_bit, cnt_byte, cnt_num;
path=0;
cnt_num=0;
do{
//(issue the 'ROM search' command)
if( 0 == OW_WriteCmd(OW_SEARCH_ROM) ) return 0;
OW_Wait_TX();
OW_ClearBuff(); // clear RX buffer
next = 0; // next path to follow
pos = 1; // path bit pointer
for(cnt_byte = 0; cnt_byte != 8; cnt_byte++){
buf[cnt_num*8 + cnt_byte] = 0;
for(cnt_bit = 0; cnt_bit != 8; cnt_bit++){
//(read two bits, 'bit' and 'chk', from the 1-wire bus)
OW_SendBits(OW_R, 2);
OW_Wait_TX();
bit = -----OW_ReadByte();
chk = bit & 0x02; // bit 1
bit = bit & 0x01; // bit 0
if(bit && chk) return 0; // error
if(!bit && !chk){ // collision, both are zero
if (pos & path) bit = 1; // if we've been here before
else next = (path&(pos-1)) | pos; // else, new branch for next
pos <<= 1;
}
//(save this bit as part of the current ROM value)
if (bit) buf[cnt_num*8 + cnt_byte]|=(1<<cnt_bit);
//(write 'bit' to the 1-wire bus)
OW_SendBits(bit, 1);
OW_Wait_TX();
}
}
path=next;
cnt_num++;
}while(path && cnt_num < num);
return cnt_num;
}*/

View File

@@ -0,0 +1,140 @@
/*
* onewire.h
*
* 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 __ONEWIRE_H__
#define __ONEWIRE_H__
#include "main.h"
#include "hardware_ini.h"
// 20 bytes x 8bits
#define TIM2_DMABUFF_SIZE 160
// freq = 1MHz
// ARR values: 1000 for reset, 100 for data in/out
// CCR4 values: 500 for reset, 60 for sending 0 or reading, <15 for sending 1
// CCR3 values: >550 if there's devices on line (on reset), >12 (typ.15) - read 0, < 12 (typ.1) - read 1
#define RESET_LEN ((uint16_t)1000)
#define BIT_LEN ((uint16_t)100)
#define RESET_P ((uint16_t)500)
#define BIT_ONE_P ((uint16_t)10)
#define BIT_ZERO_P ((uint16_t)60)
#define BIT_READ_P ((uint16_t)5)
#define RESET_BARRIER ((uint16_t)550)
#define ONE_ZERO_BARRIER ((uint16_t)10)
#define ERR_TEMP_VAL ((int32_t)200000)
typedef struct{
uint8_t bytes[8];
} OW_ID;
extern OW_ID id_array[];
#define OW_MAX_NUM 8
void init_ow_dmatimer();
void run_dmatimer();
extern uint8_t ow_done;
#define OW_READY() (ow_done)
void ow_dma_on();
uint8_t OW_add_byte(uint8_t ow_byte);
uint8_t OW_add_read_seq(uint8_t Nbytes);
void read_from_OWbuf(uint8_t start_idx, uint8_t N, uint8_t *outbuf);
void ow_reset();
uint8_t OW_get_reset_status();
extern int tum2buff_ctr;
#define OW_reset_buffer() do{tum2buff_ctr = 0;}while(0)
extern uint8_t ow_data_ready;
extern uint8_t ow_measurements_done;
#define OW_DATA_READY() (ow_data_ready)
#define OW_CLEAR_READY_FLAG() do{ow_data_ready = 0;}while(0)
#define OW_MEASUREMENTS_DONE() (ow_measurements_done)
#define OW_CLEAR_DONE_FLAG() do{ow_measurements_done = 0;}while(0)
void OW_process();
void OW_fill_next_ID();
void OW_send_read_seq();
uint8_t OW_Send(uint8_t sendReset, uint8_t *command, uint8_t cLen);
extern int32_t temperature;
extern int8_t Ncur;
void OW_read_next_temp();
#define OW_current_temp() (temperature)
#define OW_current_num() (Ncur)
/*
* thermometer commands
* send them with bus reset!
*/
// find devices
#define OW_SEARCH_ROM (0xf0)
// read device (when it is alone on the bus)
#define OW_READ_ROM (0x33)
// send device ID (after this command - 8 bytes of ID)
#define OW_MATCH_ROM (0x55)
// broadcast command
#define OW_SKIP_ROM (0xcc)
// find devices with critical conditions
#define OW_ALARM_SEARCH (0xec)
/*
* thermometer functions
* send them without bus reset!
*/
// start themperature reading
#define OW_CONVERT_T (0x44)
// write critical temperature to device's RAM
#define OW_SCRATCHPAD (0x4e)
// read whole device flash
#define OW_READ_SCRATCHPAD (0xbe)
// copy critical themperature from device's RAM to its EEPROM
#define OW_COPY_SCRATCHPAD (0x48)
// copy critical themperature from EEPROM to RAM (when power on this operation runs automatically)
#define OW_RECALL_E2 (0xb8)
// check whether there is devices wich power up from bus
#define OW_READ_POWER_SUPPLY (0xb4)
/*
* thermometer identificator is: 8bits CRC, 48bits serial, 8bits device code (10h)
* Critical temperatures is T_H and T_L
* T_L is lowest allowed temperature
* T_H is highest -//-
* format T_H and T_L: 1bit sigh + 7bits of data
*/
/*
* RAM register:
* 0 - themperature: 1 ADU == 0.5 degrC
* 1 - sign (0 - T>0 degrC ==> T=byte0; 1 - T<0 degrC ==> T=byte0-0xff+1)
* 2 - T_H
* 3 - T_L
* 4 - 0xff (reserved)
* 5 - 0xff (reserved)
* 6 - COUNT_REMAIN (0x0c)
* 7 - COUNT PER DEGR (0x10)
* 8 - CRC
*/
#endif // __ONEWIRE_H__

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

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

View File

@@ -0,0 +1,243 @@
/*
* 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 "onewire.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");
P("1\tswitch LED D1 state\n");
P("2\tswitch LED D2 state\n");
P("R\tstart reading temperature\n");
P("P\tread DS18 ID\n");
P("Q\tget temperature\n");
}
/**
* show entered integer value
*/
uint8_t show_int(int32_t v){
newline();
print_int(v);
newline();
return 0;
}
/**
* parse command buffer buf with length len
* return 0 if buffer processed or len if there's not enough data in buffer
*/
int parse_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 '1':
gpio_toggle(LEDS_PORT, LED_D1_PIN);
break;
case '2':
gpio_toggle(LEDS_PORT, LED_D2_PIN);
break;
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 'P':
OW_fill_next_ID();
break;
case 'Q':
if(OW_MEASUREMENTS_DONE())
OW_read_next_temp();
else
P("Wait for measurements ends or start another\n");
break;
case 'R':
OW_send_read_seq();
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++);
}
void ERR(char *wrd){
if(!wrd) return;
while(*wrd) usb_send(*((uint8_t*)wrd++));
usb_send('\n');
}
/**
* 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');
}
void OW_printID(uint8_t N){
void putc(uint8_t c){
if(c < 10)
usb_send(c + '0');
else
usb_send(c + 'a' - 10);
}
int i;
uint8_t *b = id_array[N].bytes;
usb_send('0'); usb_send('x'); // prefix 0x
for(i = 0; i < 8; i++){
putc(b[i] >> 4);
putc(b[i] & 0x0f);
}
usb_send('\n');
}

View File

@@ -0,0 +1,51 @@
/*
* 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)
#define INT(N) do{print_int(N);}while(0)
#else
#define DBG(a)
#define INT(N)
#endif
typedef uint8_t (*intfun)(int32_t);
void ERR(char *wrd);
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 parse_incoming_buf(char *buf, int len);
void OW_printID(uint8_t N);
#endif // __USER_PROTO_H__

View File

@@ -0,0 +1,133 @@
BINARY = dma_gpio
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)

View File

@@ -0,0 +1,5 @@
Template of USB-CDC
written for chinese devboard based on STM32F103R8T6
Press H for help

View File

@@ -0,0 +1,310 @@
/*
* 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,
};
uint8_t 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
}
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));
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);
}

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 uint8_t usbdatabuf[];
extern int usbdatalen;
usbd_device *USB_init();
void usb_send(uint8_t byte);
void usb_send_buffer();
#endif // __CCDCACM_H__

Binary file not shown.

View File

@@ -0,0 +1,74 @@
/*
* dmagpio.c
*
* Copyright 2016 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 "dmagpio.h"
#include "user_proto.h"
int transfer_complete = 0;
static uint16_t gpiobuff[128] = {0};
void dmagpio_init(){
// init TIM2 & DMA1ch2 (TIM2UP)
rcc_periph_clock_enable(RCC_TIM2);
rcc_periph_clock_enable(RCC_DMA1);
timer_reset(TIM2);
// timer have frequency of 1MHz
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
// 72MHz div 18 = 4MHz
TIM2_PSC = 0; // prescaler is (div - 1)
TIM2_ARR = 1; // 36MHz (6.25)
TIM2_DIER = TIM_DIER_UDE;// | TIM_DIER_UIE;
dma_channel_reset(DMA1, DMA_CHANNEL2);
// mem2mem, medium prio, 8bits, memory increment, read from mem, transfer complete en
DMA1_CCR2 = DMA_CCR_PL_MEDIUM | DMA_CCR_MSIZE_16BIT |
DMA_CCR_PSIZE_16BIT | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE ;
nvic_enable_irq(NVIC_DMA1_CHANNEL2_IRQ);
// target address:
DMA1_CPAR2 = DMAGPIO_TARGADDR;
DMA1_CMAR2 = (uint32_t) gpiobuff;
}
void dmagpio_transfer(uint8_t *databuf, uint32_t length){
while(DMA1_CCR2 & DMA_CCR_EN);
transfer_complete = 0;
DMA1_IFCR = 0xff00; // clear all flags for ch2
// buffer length
DMA1_CNDTR2 = length;
uint32_t i;
for(i = 0; i < length; ++i) gpiobuff[i] = databuf[i];
TIM2_CR1 |= TIM_CR1_CEN; // run timer
DMA1_CCR2 |= DMA_CCR_EN;
}
void dma1_channel2_isr(){
if(DMA1_ISR & DMA_ISR_TCIF2){
transfer_complete = 1;
// stop timer & turn off DMA
TIM2_CR1 &= ~TIM_CR1_CEN;
DMA1_CCR2 &= ~DMA_CCR_EN;
DMA1_IFCR = DMA_IFCR_CTCIF2; // clear flag
}else if(DMA1_ISR & DMA_ISR_TEIF2){
P("Error\n");
DMA1_IFCR = DMA_IFCR_CTEIF2;
TIM2_CR1 &= ~TIM_CR1_CEN;
DMA1_CCR2 &= ~DMA_CCR_EN;
}
}

View File

@@ -0,0 +1,32 @@
/*
* dmagpio.h
*
* Copyright 2016 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 __DMAGPIO_H__
#define __DMAGPIO_H__
#include "main.h"
#include "hardware_ini.h"
void dmagpio_init();
void dmagpio_transfer(uint8_t *databuf, uint32_t length);
extern int transfer_complete;
#endif // __DMAGPIO_H__

View File

@@ -0,0 +1,72 @@
/*
* 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);
// DMAGPIO
gpio_set_mode(LCD_CONTROL_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
LCD_CS_PIN | LCD_RD_PIN | LCD_RS_PIN | LCD_WR_PIN | LCD_RST_PIN);
LCD_write(); // set pins as out
/*
// 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(8999); // 9000 pulses: 1kHz
systick_interrupt_enable();
systick_counter_enable();
}

View File

@@ -0,0 +1,95 @@
/*
* 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();
/*
* DMA to GPIO port & pins (mask) - PA0..PA7
*/
#define DMAGPIO_PORT GPIOA
#define DMAGPIO_PINS 0xff
#define DMAGPIO_TARGADDR ((uint32_t)&(GPIOA_ODR))
#define LCD_write() do{gpio_set_mode(DMAGPIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, DMAGPIO_PINS);}while(0)
//#define LCD_read() do{gpio_set_mode(DMAGPIO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, DMAGPIO_PINS);}while(0)
#define LCD_read() do{gpio_set_mode(DMAGPIO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, DMAGPIO_PINS); GPIO_ODR(DMAGPIO_PORT) = 0;}while(0)
// LCD control pins (PB10..PB14)
#define LCD_CONTROL_PORT GPIOB
#define LCD_CS_PIN GPIO12
#define LCD_RS_PIN GPIO11
#define LCD_WR_PIN GPIO14
#define LCD_RD_PIN GPIO13
#define LCD_RST_PIN GPIO10
// macro for control pins manipulation
#define CS_set do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_CS_PIN;}while(0)
#define RS_set do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RS_PIN;}while(0)
#define RD_set do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RD_PIN;}while(0)
#define WR_set do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_WR_PIN;}while(0)
#define CS_clear do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_CS_PIN << 16;}while(0)
#define RS_clear do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RS_PIN << 16;}while(0)
#define RD_clear do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RD_PIN << 16;}while(0)
#define WR_clear do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_WR_PIN << 16;}while(0)
#define RST_set do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RST_PIN;}while(0)
#define RST_clear do{GPIO_BSRR(LCD_CONTROL_PORT) = LCD_RST_PIN << 16;}while(0)
#define LCD_wrbyte(x) do{GPIO_ODR(DMAGPIO_PORT) = x;}while(0)
/*
#define LCD_wrbyte(x) do{GPIO_BSRR(DMAGPIO_PORT) = DMAGPIO_PINS << 16; \
GPIO_BSRR(DMAGPIO_PORT) = x;}while(0)
*/
#define LCD_rdbyte() (GPIO_IDR(DMAGPIO_PORT) & DMAGPIO_PINS)
/*
* 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()
#endif // __HARDWARE_INI_H__

433
deprecated/F1/2.8TFT/lcd.c Normal file
View File

@@ -0,0 +1,433 @@
/*
* lcd.c
*
* Copyright 2016 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 "lcd.h"
#include "hardware_ini.h"
#include "dmagpio.h"
#include "registers.h"
static uint16_t LCD_id = 0;
#define nop() __asm__("nop")
uint8_t readbyte(){
RD_clear;
nop();
uint8_t byte = LCD_rdbyte();
RD_set;
nop();
return byte;
}
void writebyte(uint8_t b){
LCD_wrbyte(b);
WR_clear;
nop();
WR_set;
nop();
}
void writereg(uint16_t r){
LCD_wrbyte(r >> 8);
RS_clear;
WR_clear;
nop();
WR_set;
LCD_wrbyte(r & 0xff);
nop();
WR_clear;
nop();
WR_set;
RS_set;
}
uint16_t read_reg(uint16_t reg){
uint32_t dat = 0;
CS_clear; // active
writereg(reg);
LCD_read();
dat = readbyte() << 8;
dat |= readbyte();
CS_set;
LCD_write(); // restore dir to out
return dat;
}
void write_reg(uint16_t reg, uint16_t dat){
CS_clear; // active
writereg(reg);
RS_set; // data
writebyte(dat >> 8);
writebyte(dat && 0xff);
CS_set;
}
/*
typedef union{
uint8_t bytes[4];
uint32_t word;
}word32;
void write16_16(uint16_t reg, uint16_t dat){
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg && 0xff);
RS_set; // data
writebyte(dat >> 8);
writebyte(dat && 0xff);
CS_set;
}
void write_reg16_var(uint16_t reg, uint32_t dat, uint8_t len){
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg && 0xff);
RS_set; // data
word32 w;
w.word = dat;
--len;
for(i = len; i > -1; --i){
writebyte(w.bytes[i]);
}
CS_set;
}
void write_reg_var(uint8_t reg, uint32_t dat, uint8_t len){
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg);
RS_set; // data
word32 w;
w.word = dat;
--len;
for(i = len; i > -1; --i){
writebyte(w.bytes[i]);
}
CS_set;
}
uint32_t read_reg_var(uint8_t reg, uint8_t len){
uint32_t dat = 0;
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg);
LCD_read();
RS_set; // data
for(i = 0; i < len; ++i){
dat <<= 8;
dat = dat | readbyte();
}
CS_set;
return dat;
}
uint32_t read16_reg_var(uint16_t reg, uint8_t len){
uint32_t dat = 0;
int i;
CS_clear; // active
RS_clear; // register
LCD_write(); // dir: out
writebyte(reg >> 8);
writebyte(reg & 0xff);
LCD_read();
RS_set; // data
for(i = 0; i < len; ++i){
dat <<= 8;
dat = dat | readbyte();
}
CS_set;
return dat;
}
*/
uint16_t LCD_status_read(){
uint16_t dat;
LCD_read();
CS_clear;
RS_clear;
dat = readbyte() << 8;
dat |= readbyte();
RS_set;
CS_set;
LCD_write();
return dat;
}
void LCD_reset(){
CS_set; RS_set; WR_set; RD_set;
LCD_write();
LCD_wrbyte(0xff);
RST_clear;
Delay(300);
RST_set;
Delay(100);
write_reg(0,1);
Delay(100);
/* CS_clear; RS_clear;
int i;
for(i = 0; i < 4; ++i) writebyte(0);
RS_set; CS_set;
*/
}
/**
* read LCD identification
*/
uint16_t LCD_read_id(){
write_reg(0,0);
LCD_id = read_reg(0);
write_reg(0,1);
/*if(read8_32(0x04) == 0x8000){
write8_24(HX8357D_SETC, 0xFF8357);
Delay(10);
if(read8_32(0xD0) == 0x990000){
LCD_id = 0x8357;
return 0x8357;
}
}
if(read8_32(0xD3) == 0x9341){
LCD_id = 0x9341;
return 0x9341;
}*/
return LCD_id;
}
#define TFTLCD_DELAY 0xfff
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DISP_CTRL1 , 0x0121, // 0x07
ILI932X_DRIV_OUT_CTRL , 0x0100, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x0030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0001, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
/*
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 200,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0227, // 0x11
TFTLCD_DELAY , 50,
//ILI932X_POW_CTRL3 , 0x001A, // 0x12
ILI932X_POW_CTRL3 , 0x001D, // 0x12
TFTLCD_DELAY , 50,
//ILI932X_POW_CTRL4 , 0x1800, // 0x13
ILI932X_POW_CTRL4 , 0x0800, // 0x13
//ILI932X_POW_CTRL7 , 0x002A, // 0x29
ILI932X_POW_CTRL7 , 0x0012, // 0x29
*/
ILI932X_POW_CTRL1 , 0x16b0, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0138, // 0x12
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
ILI932X_POW_CTRL7 , 0x0000, // 0x29
TFTLCD_DELAY , 200,
ILI932X_FRM_RATE_COL_CTRL, 0x0000, // 0x2B (100Hz)
TFTLCD_DELAY , 50,
ILI932X_GAMMA_CTRL1 , 0x0000, // 0x30
ILI932X_GAMMA_CTRL2 , 0x0000, // 0x31
ILI932X_GAMMA_CTRL3 , 0x0000, // 0x32
ILI932X_GAMMA_CTRL4 , 0x0206, // 0x35
ILI932X_GAMMA_CTRL5 , 0x0808, // 0x36
ILI932X_GAMMA_CTRL6 , 0x0007, // 0x37
ILI932X_GAMMA_CTRL7 , 0x0201, // 0x38
ILI932X_GAMMA_CTRL8 , 0x0000, // 0x39
ILI932X_GAMMA_CTRL9 , 0x0000, // 0x3C
ILI932X_GAMMA_CTRL10 , 0x0000, // 0x3D
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
//ILI932X_GATE_SCAN_CTRL1 , 0xA700, // 0x60
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
//ILI932X_GATE_SCAN_CTRL2 , 0x0003, // 0x61
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0003, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
TFTLCD_DELAY , 50,
//ILI932X_DISP_CTRL1 , 0x013b, // 0x07 - 8bit color
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};
/*
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DRIV_OUT_CTRL , 0x0000, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x1030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0003, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
ILI932X_DISP_CTRL1 , 0x0021, // 0x07
TFTLCD_DELAY , 10,
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL3 , 0x0118, // 0x12
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL7 , 0x0012, // 0x29
ILI932X_FRM_RATE_COL_CTRL, 0x000B, // 0x2B
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0001, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};*/
/*
static const uint16_t ILI932x_regValues[] = {
ILI932X_START_OSC , 0x0001, // 0x00
TFTLCD_DELAY , 100,
ILI932X_DRIV_OUT_CTRL , 0x0000, // 0x01
ILI932X_DRIV_WAV_CTRL , 0x0700, // 0x02
ILI932X_ENTRY_MOD , 0x1030, // 0x03
ILI932X_RESIZE_CTRL , 0x0000, // 0x04
ILI932X_DISP_CTRL2 , 0x0202, // 0x08
ILI932X_DISP_CTRL3 , 0x0000, // 0x09
ILI932X_DISP_CTRL4 , 0x0000, // 0x0A
ILI932X_RGB_DISP_IF_CTRL1, 0x0003, // 0x0C
ILI932X_FRM_MARKER_POS , 0x0000, // 0x0D
ILI932X_RGB_DISP_IF_CTRL2, 0x0000, // 0x0F
ILI932X_DISP_CTRL1 , 0x0011, // 0x07
TFTLCD_DELAY , 10,
ILI932X_POW_CTRL1 , 0x0000, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
ILI932X_POW_CTRL3 , 0x0000, // 0x12
ILI932X_POW_CTRL4 , 0x0000, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL1 , 0x1690, // 0x10
ILI932X_POW_CTRL2 , 0x0007, // 0x11
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL3 , 0x0118, // 0x12
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL4 , 0x0b00, // 0x13
TFTLCD_DELAY , 100,
ILI932X_POW_CTRL7 , 0x0012, // 0x29
ILI932X_FRM_RATE_COL_CTRL, 0x000B, // 0x2B
ILI932X_GRAM_HOR_AD , 0x0000, // 0x20
ILI932X_GRAM_VER_AD , 0x0000, // 0x21
ILI932X_HOR_START_AD , 0x0000, // 0x50
ILI932X_HOR_END_AD , TFTWIDTH-1, // 0x51
ILI932X_VER_START_AD , 0x0000, // 0x52
ILI932X_VER_END_AD , TFTHEIGHT-1, // 0x53
ILI932X_GATE_SCAN_CTRL1 , 0x2700, // 0x60
ILI932X_GATE_SCAN_CTRL2 , 0x0001, // 0x61
ILI932X_GATE_SCAN_CTRL3 , 0x0000, // 0x6A
ILI932X_PANEL_IF_CTRL1 , 0x0010, // 0x90
ILI932X_PANEL_IF_CTRL2 , 0x0000, // 0x92
ILI932X_PANEL_IF_CTRL3 , 0x0001, // 0x93
ILI932X_PANEL_IF_CTRL4 , 0x0110, // 0x95
ILI932X_PANEL_IF_CTRL5 , 0x0000, // 0x97
ILI932X_PANEL_IF_CTRL6 , 0x0000, // 0x98
ILI932X_DISP_CTRL1 , 0x0133, // 0x07
};
*/
/**
* try to init display
* return 0 if failed
*/
uint16_t LCD_init(){
//if(LCD_id == 0)
LCD_read_id();
if(LCD_id > 0x931f && LCD_id < 0x932a){ // 932x
// LCD_id = 0x9320; // make it simple!
int i, s = sizeof(ILI932x_regValues)/sizeof(uint16_t);
for(i = 0; i < s;){
uint16_t a = ILI932x_regValues[i++];
uint16_t b = ILI932x_regValues[i++];
if(a == TFTLCD_DELAY) Delay(b);
else write_reg(a, b);
}
uint16_t addr;
for(addr = 0x80; addr < 0x86; ++addr)
write_reg(addr, 0);
Delay(300);
return LCD_id;
}
//LCD_reset();
return LCD_id;
}
/**
* put point to current position incrementing coordinates
*/
void putpoint(uint16_t colr){
int i;
if(LCD_id == 0) return;
LCD_write(); // dir: out
CS_clear; // active
writereg(ILI932X_RW_GRAM);
for(i = 0; i < 500; ++i){
writebyte(colr >> 8);
writebyte(colr && 0xff);
}
CS_set;
//if(LCD_id == 0x9320){
//}
}
void setpix(uint16_t x, uint16_t y, uint16_t colr){
write_reg(ILI932X_GRAM_HOR_AD, x);
write_reg(ILI932X_GRAM_VER_AD, y);
write_reg(ILI932X_RW_GRAM, colr);
}

View File

@@ -0,0 +1,68 @@
/*
* lcd.h
*
* Copyright 2016 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 __LCD_H__
#define __LCD_H__
#define TFTWIDTH 240
#define TFTHEIGHT 320
#define DWT_CYCCNT *(volatile uint32_t *)0xE0001004
#define DWT_CONTROL *(volatile uint32_t *)0xE0001000
#define SCB_DEMCR *(volatile uint32_t *)0xE000EDFC
// pause for 150ns
#define pause() do{SCB_DEMCR |= 0x01000000; DWT_CYCCNT = 0; DWT_CONTROL|= 1; \
while(DWT_CYCCNT < 3);}while(0)
//#define pause() do{}while(0)
uint16_t read_reg(uint16_t reg);
void write_reg(uint16_t reg, uint16_t dat);
/*
uint32_t read_reg_var(uint8_t reg, uint8_t len);
uint32_t read16_reg_var(uint16_t reg, uint8_t len);
#define write8_32(r,d) do{write_reg_var(r,d,4);}while(0)
#define write8_24(r,d) do{write_reg_var(r,d,3);}while(0)
#define write8_16(r,d) do{write_reg_var(r,d,2);}while(0)
#define write16_32(r,d) do{write_reg16_var(r,d,4);}while(0)
#define write16_24(r,d) do{write_reg16_var(r,d,3);}while(0)
//#define write16_16(r,d) do{write_reg16_var(r,d,2);}while(0)
void write16_16(uint16_t reg, uint16_t dat);
#define read8_32(x) (read_reg_var(x, 4))
#define read8_16(x) ((uint16_t)(read_reg_var(x, 2)))
#define read16_32(x) (read16_reg_var(x, 4))
#define read16_16(x) ((uint16_t)(read16_reg_var(x, 2)))
*/
uint16_t LCD_status_read();
uint16_t LCD_read_id();
void LCD_reset();
uint16_t LCD_init();
void putpoint(uint16_t colr);
void setpix(uint16_t x, uint16_t y, uint16_t colr);
#endif // __LCD_H__

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

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

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

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

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

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

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

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

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

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

128
deprecated/F1/2.8TFT/main.c Normal file
View File

@@ -0,0 +1,128 @@
/*
* 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 "dmagpio.h"
#include "lcd.h"
#include "registers.h"
volatile uint32_t Timer = 0; // global timer (milliseconds)
usbd_device *usbd_dev;
int main(){
uint32_t Old_timer = 0;
// RCC clocking: 8MHz oscillator -> 72MHz system
rcc_clock_setup_in_hse_8mhz_out_72mhz();
// SysTick is a system timer with 1ms period
SysTick_init();
// disable JTAG to use PA13/PA14
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, 0);
GPIO_init();
usb_disconnect(); // turn off USB while initializing all
// USB
usbd_dev = USB_init();
dmagpio_init();
usb_connect(); // turn on USB
LCD_reset();
int oldusblen = 0, x = 0, y = 0;
int id = LCD_init();
if(!id) P("failed to init LCD\n");
uint16_t colr = 0;
while(1){
usbd_poll(usbd_dev);
if(usbdatalen != oldusblen){ // there's something in USB buffer
parse_incoming_buf(usbdatabuf, &usbdatalen);
oldusblen = usbdatalen;
id = 0;
}
if(transfer_complete){
P("transfered\n");
transfer_complete = 0;
}
setpix(x++, y++, colr);
if(x > 200) x = 0;
if(y > 200) y = 0;
if(Timer - Old_timer > 999){ // one-second cycle
Old_timer += 1000;
P("Display id: ");
print_hex((uint8_t*)&id, 2);
newline();
//write_reg(ILI932X_DISP_CTRL1, 0x0133);
if(id){
uint16_t r = read_reg(ILI932X_RW_GRAM);
print_hex((uint8_t*)&r, 2);
/*P(", status: ");
r = LCD_status_read();
print_hex((uint8_t*)&r, 2);*/
newline();
uint16_t i;
for(i = 0; i < 0x29; ++i){
r = read_reg(i);
print_hex((uint8_t*)&i, 2); P(" = ");
print_hex((uint8_t*)&r, 2); usb_send(' ');
r = read_reg(i); print_hex((uint8_t*)&r, 2);
newline();
}
putpoint(colr);
colr += 32;
}else{
LCD_reset();
id = LCD_init();
if(!id) P("failed to init LCD\n");
}
}else if(Timer < Old_timer){ // Timer overflow
Old_timer = 0;
}
}
}
/**
* SysTick interrupt: increment global time & send data buffer through USB
*/
void sys_tick_handler(){
Timer++;
usbd_poll(usbd_dev);
usb_send_buffer();
}
// pause function, delay in ms
void Delay(uint16_t _U_ time){
uint32_t waitto = Timer + time;
while(Timer < waitto);
}
/**
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
* with ' ' as delimeter
*/
void print_time(){
print_int(Timer);
}

View File

@@ -0,0 +1,53 @@
/*
* 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 <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/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/timer.h>
#include "sync.h" // mutexes
#include "user_proto.h"
#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__

View File

@@ -0,0 +1,172 @@
// Register names from Peter Barrett's Microtouch code
#define ILI932X_START_OSC 0x00
#define ILI932X_DRIV_OUT_CTRL 0x01
#define ILI932X_DRIV_WAV_CTRL 0x02
#define ILI932X_ENTRY_MOD 0x03
#define ILI932X_RESIZE_CTRL 0x04
#define ILI932X_DISP_CTRL1 0x07
#define ILI932X_DISP_CTRL2 0x08
#define ILI932X_DISP_CTRL3 0x09
#define ILI932X_DISP_CTRL4 0x0A
#define ILI932X_RGB_DISP_IF_CTRL1 0x0C
#define ILI932X_FRM_MARKER_POS 0x0D
#define ILI932X_RGB_DISP_IF_CTRL2 0x0F
#define ILI932X_POW_CTRL1 0x10
#define ILI932X_POW_CTRL2 0x11
#define ILI932X_POW_CTRL3 0x12
#define ILI932X_POW_CTRL4 0x13
#define ILI932X_GRAM_HOR_AD 0x20
#define ILI932X_GRAM_VER_AD 0x21
#define ILI932X_RW_GRAM 0x22
#define ILI932X_POW_CTRL7 0x29
#define ILI932X_FRM_RATE_COL_CTRL 0x2B
#define ILI932X_GAMMA_CTRL1 0x30
#define ILI932X_GAMMA_CTRL2 0x31
#define ILI932X_GAMMA_CTRL3 0x32
#define ILI932X_GAMMA_CTRL4 0x35
#define ILI932X_GAMMA_CTRL5 0x36
#define ILI932X_GAMMA_CTRL6 0x37
#define ILI932X_GAMMA_CTRL7 0x38
#define ILI932X_GAMMA_CTRL8 0x39
#define ILI932X_GAMMA_CTRL9 0x3C
#define ILI932X_GAMMA_CTRL10 0x3D
#define ILI932X_HOR_START_AD 0x50
#define ILI932X_HOR_END_AD 0x51
#define ILI932X_VER_START_AD 0x52
#define ILI932X_VER_END_AD 0x53
#define ILI932X_GATE_SCAN_CTRL1 0x60
#define ILI932X_GATE_SCAN_CTRL2 0x61
#define ILI932X_GATE_SCAN_CTRL3 0x6A
#define ILI932X_PART_IMG1_DISP_POS 0x80
#define ILI932X_PART_IMG1_START_AD 0x81
#define ILI932X_PART_IMG1_END_AD 0x82
#define ILI932X_PART_IMG2_DISP_POS 0x83
#define ILI932X_PART_IMG2_START_AD 0x84
#define ILI932X_PART_IMG2_END_AD 0x85
#define ILI932X_PANEL_IF_CTRL1 0x90
#define ILI932X_PANEL_IF_CTRL2 0x92
#define ILI932X_PANEL_IF_CTRL3 0x93
#define ILI932X_PANEL_IF_CTRL4 0x95
#define ILI932X_PANEL_IF_CTRL5 0x97
#define ILI932X_PANEL_IF_CTRL6 0x98
#define HX8347G_COLADDRSTART_HI 0x02
#define HX8347G_COLADDRSTART_LO 0x03
#define HX8347G_COLADDREND_HI 0x04
#define HX8347G_COLADDREND_LO 0x05
#define HX8347G_ROWADDRSTART_HI 0x06
#define HX8347G_ROWADDRSTART_LO 0x07
#define HX8347G_ROWADDREND_HI 0x08
#define HX8347G_ROWADDREND_LO 0x09
#define HX8347G_MEMACCESS 0x16
#define ILI9341_SOFTRESET 0x01
#define ILI9341_SLEEPIN 0x10
#define ILI9341_SLEEPOUT 0x11
#define ILI9341_NORMALDISP 0x13
#define ILI9341_INVERTOFF 0x20
#define ILI9341_INVERTON 0x21
#define ILI9341_GAMMASET 0x26
#define ILI9341_DISPLAYOFF 0x28
#define ILI9341_DISPLAYON 0x29
#define ILI9341_COLADDRSET 0x2A
#define ILI9341_PAGEADDRSET 0x2B
#define ILI9341_MEMORYWRITE 0x2C
#define ILI9341_PIXELFORMAT 0x3A
#define ILI9341_FRAMECONTROL 0xB1
#define ILI9341_DISPLAYFUNC 0xB6
#define ILI9341_ENTRYMODE 0xB7
#define ILI9341_POWERCONTROL1 0xC0
#define ILI9341_POWERCONTROL2 0xC1
#define ILI9341_VCOMCONTROL1 0xC5
#define ILI9341_VCOMCONTROL2 0xC7
#define ILI9341_MEMCONTROL 0x36
#define ILI9341_MADCTL 0x36
#define ILI9341_MADCTL_MY 0x80
#define ILI9341_MADCTL_MX 0x40
#define ILI9341_MADCTL_MV 0x20
#define ILI9341_MADCTL_ML 0x10
#define ILI9341_MADCTL_RGB 0x00
#define ILI9341_MADCTL_BGR 0x08
#define ILI9341_MADCTL_MH 0x04
#define HX8357_NOP 0x00
#define HX8357_SWRESET 0x01
#define HX8357_RDDID 0x04
#define HX8357_RDDST 0x09
#define HX8357B_RDPOWMODE 0x0A
#define HX8357B_RDMADCTL 0x0B
#define HX8357B_RDCOLMOD 0x0C
#define HX8357B_RDDIM 0x0D
#define HX8357B_RDDSDR 0x0F
#define HX8357_SLPIN 0x10
#define HX8357_SLPOUT 0x11
#define HX8357B_PTLON 0x12
#define HX8357B_NORON 0x13
#define HX8357_INVOFF 0x20
#define HX8357_INVON 0x21
#define HX8357_DISPOFF 0x28
#define HX8357_DISPON 0x29
#define HX8357_CASET 0x2A
#define HX8357_PASET 0x2B
#define HX8357_RAMWR 0x2C
#define HX8357_RAMRD 0x2E
#define HX8357B_PTLAR 0x30
#define HX8357_TEON 0x35
#define HX8357_TEARLINE 0x44
#define HX8357_MADCTL 0x36
#define HX8357_COLMOD 0x3A
#define HX8357_SETOSC 0xB0
#define HX8357_SETPWR1 0xB1
#define HX8357B_SETDISPLAY 0xB2
#define HX8357_SETRGB 0xB3
#define HX8357D_SETCOM 0xB6
#define HX8357B_SETDISPMODE 0xB4
#define HX8357D_SETCYC 0xB4
#define HX8357B_SETOTP 0xB7
#define HX8357D_SETC 0xB9
#define HX8357B_SET_PANEL_DRIVING 0xC0
#define HX8357D_SETSTBA 0xC0
#define HX8357B_SETDGC 0xC1
#define HX8357B_SETID 0xC3
#define HX8357B_SETDDB 0xC4
#define HX8357B_SETDISPLAYFRAME 0xC5
#define HX8357B_GAMMASET 0xC8
#define HX8357B_SETCABC 0xC9
#define HX8357_SETPANEL 0xCC
#define HX8357B_SETPOWER 0xD0
#define HX8357B_SETVCOM 0xD1
#define HX8357B_SETPWRNORMAL 0xD2
#define HX8357B_RDID1 0xDA
#define HX8357B_RDID2 0xDB
#define HX8357B_RDID3 0xDC
#define HX8357B_RDID4 0xDD
#define HX8357D_SETGAMMA 0xE0
#define HX8357B_SETGAMMA 0xC8
#define HX8357B_SETPANELRELATED 0xE9
#define HX8357B_MADCTL_MY 0x80
#define HX8357B_MADCTL_MX 0x40
#define HX8357B_MADCTL_MV 0x20
#define HX8357B_MADCTL_ML 0x10
#define HX8357B_MADCTL_RGB 0x00
#define HX8357B_MADCTL_BGR 0x08
#define HX8357B_MADCTL_MH 0x04

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

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

View File

@@ -0,0 +1,93 @@
/*
* 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 "dmagpio.h"
/**
* parce command buffer buf with length len
* return 0 if buffer processed or len if there's not enough data in buffer
*/
void parse_incoming_buf(uint8_t *buf, int *len){
static int lastidx = 0;
int l = *len;
for(; lastidx < l; ++lastidx){
uint8_t cmd = buf[lastidx];
usb_send(cmd);
if(cmd == '\n'){
dmagpio_transfer(buf, *len);
*len = 0;
lastidx = 0;
return;
}
}
}
/**
* Send char array wrd thru USB
*/
void prnt(uint8_t *wrd){
if(!wrd) return;
while(*wrd) usb_send(*wrd++);
}
/**
* 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');
}

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);
void parse_incoming_buf(uint8_t *buf, int *len);
#endif // __USER_PROTO_H__

View File

@@ -0,0 +1,133 @@
BINARY = dma_gpio
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)

View File

@@ -0,0 +1 @@
simple 8-bit FSMC emulation with DMA

View File

@@ -0,0 +1,310 @@
/*
* 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,
};
uint8_t 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
}
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));
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);
}

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 uint8_t usbdatabuf[];
extern int usbdatalen;
usbd_device *USB_init();
void usb_send(uint8_t byte);
void usb_send_buffer();
#endif // __CCDCACM_H__

Binary file not shown.

View File

@@ -0,0 +1,97 @@
/*
* dmagpio.c
*
* Copyright 2016 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 "dmagpio.h"
#include "user_proto.h"
int transfer_complete = 0;
static uint16_t gpiobuff[128] = {0};
void dmagpio_init(){
// init TIM2 & DMA1ch2 (TIM2UP)
rcc_periph_clock_enable(RCC_TIM2);
rcc_periph_clock_enable(RCC_DMA1);
timer_reset(TIM2);
// timer have frequency of 1MHz
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
// 72MHz div 18 = 4MHz
TIM2_PSC = 0; // prescaler is (div - 1)
TIM2_ARR = 1; // 36MHz (6.25)
TIM2_DIER = TIM_DIER_UDE;// | TIM_DIER_UIE;
//nvic_enable_irq(NVIC_TIM2_IRQ);
dma_channel_reset(DMA1, DMA_CHANNEL2);
// mem2mem, medium prio, 8bits, memory increment, read from mem, transfer complete en
//DMA1_CCR2 = DMA_CCR_MEM2MEM | DMA_CCR_PL_MEDIUM | DMA_CCR_MSIZE_16BIT |
DMA1_CCR2 = DMA_CCR_PL_MEDIUM | DMA_CCR_MSIZE_16BIT |
DMA_CCR_PSIZE_16BIT | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE ;
nvic_enable_irq(NVIC_DMA1_CHANNEL2_IRQ);
// target address:
DMA1_CPAR2 = DMAGPIO_TARGADDR;
DMA1_CMAR2 = (uint32_t) gpiobuff;
}
/*
void tim2_isr(){
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
++cntr;
GPIOA_ODR = gpiobuff[curidx];
if(++curidx >= len){
TIM2_CR1 &= ~TIM_CR1_CEN;
transfer_complete = 1;
}
TIM2_SR = 0;
}
}
*/
void dmagpio_transfer(uint8_t *databuf, uint32_t length){
while(DMA1_CCR2 & DMA_CCR_EN);
transfer_complete = 0;
DMA1_IFCR = 0xff00; // clear all flags for ch2
// memory address
//DMA1_CMAR2 = (uint32_t) databuf;
// buffer length
// DMA1_CPAR2 = DMAGPIO_TARGADDR;
// DMA1_CMAR2 = (uint32_t) gpiobuff;
DMA1_CNDTR2 = length;
uint32_t i;
for(i = 0; i < length; ++i) gpiobuff[i] = databuf[i];
TIM2_CR1 |= TIM_CR1_CEN; // run timer
DMA1_CCR2 |= DMA_CCR_EN;
}
void dma1_channel2_isr(){
if(DMA1_ISR & DMA_ISR_TCIF2){
transfer_complete = 1;
// stop timer & turn off DMA
TIM2_CR1 &= ~TIM_CR1_CEN;
DMA1_CCR2 &= ~DMA_CCR_EN;
DMA1_IFCR = DMA_IFCR_CTCIF2; // clear flag
/* uint32_t arr = TIM2_ARR;
if(arr == 1) TIM2_ARR = 71;
else TIM2_ARR = arr - 1;*/
}else if(DMA1_ISR & DMA_ISR_TEIF2){
P("Error\n");
DMA1_IFCR = DMA_IFCR_CTEIF2;
TIM2_CR1 &= ~TIM_CR1_CEN;
DMA1_CCR2 &= ~DMA_CCR_EN;
}
}

View File

@@ -0,0 +1,32 @@
/*
* dmagpio.h
*
* Copyright 2016 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 __DMAGPIO_H__
#define __DMAGPIO_H__
#include "main.h"
#include "hardware_ini.h"
void dmagpio_init();
void dmagpio_transfer(uint8_t *databuf, uint32_t length);
extern int transfer_complete;
#endif // __DMAGPIO_H__

View File

@@ -0,0 +1,72 @@
/*
* 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);
// DMAGPIO
gpio_set_mode(DMAGPIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
DMAGPIO_PINS);
/*
// 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(8999); // 9000 pulses: 1kHz
systick_interrupt_enable();
systick_counter_enable();
}

View File

@@ -0,0 +1,65 @@
/*
* 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();
/*
* DMA to GPIO port & pins (mask)
*/
#define DMAGPIO_PORT GPIOA
#define DMAGPIO_PINS 0xff
#define DMAGPIO_TARGADDR ((uint32_t)&(GPIOA_ODR))
/*
* 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()
#endif // __HARDWARE_INI_H__

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

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

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

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

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

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

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

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

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

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

View File

@@ -0,0 +1,90 @@
/*
* 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 "dmagpio.h"
volatile uint32_t Timer = 0; // global timer (milliseconds)
usbd_device *usbd_dev;
int main(){
uint32_t Old_timer = 0;
// 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();
dmagpio_init();
usb_connect(); // turn on USB
int oldusblen = 0;
while(1){
usbd_poll(usbd_dev);
if(usbdatalen != oldusblen){ // there's something in USB buffer
parse_incoming_buf(usbdatabuf, &usbdatalen);
oldusblen = usbdatalen;
}
if(transfer_complete){
P("transfered\n");
transfer_complete = 0;
}
if(Timer - Old_timer > 999){ // one-second cycle
Old_timer += 1000;
}else if(Timer < Old_timer){ // Timer overflow
Old_timer = 0;
}
}
}
/**
* SysTick interrupt: increment global time & send data buffer through USB
*/
void sys_tick_handler(){
Timer++;
usbd_poll(usbd_dev);
usb_send_buffer();
}
// pause function, delay in ms
void Delay(uint16_t _U_ time){
uint32_t waitto = Timer + time;
while(Timer < waitto);
}
/**
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
* with ' ' as delimeter
*/
void print_time(){
print_int(Timer);
}

View File

@@ -0,0 +1,53 @@
/*
* 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 <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/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/timer.h>
#include "sync.h" // mutexes
#include "user_proto.h"
#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__

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

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

View File

@@ -0,0 +1,93 @@
/*
* 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 "dmagpio.h"
/**
* parse command buffer buf with length len
* return 0 if buffer processed or len if there's not enough data in buffer
*/
void parse_incoming_buf(uint8_t *buf, int *len){
static int lastidx = 0;
int l = *len;
for(; lastidx < l; ++lastidx){
uint8_t cmd = buf[lastidx];
usb_send(cmd);
if(cmd == '\n'){
dmagpio_transfer(buf, *len);
*len = 0;
lastidx = 0;
return;
}
}
}
/**
* Send char array wrd thru USB
*/
void prnt(uint8_t *wrd){
if(!wrd) return;
while(*wrd) usb_send(*wrd++);
}
/**
* 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');
}

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);
void parse_incoming_buf(uint8_t *buf, int *len);
#endif // __USER_PROTO_H__

View File

@@ -0,0 +1,133 @@
BINARY = tim_gpio
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)

View File

@@ -0,0 +1 @@
simple FSMC emulation by timer interrupts

View File

@@ -0,0 +1,310 @@
/*
* 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,
};
uint8_t 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
}
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));
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);
}

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 uint8_t usbdatabuf[];
extern int usbdatalen;
usbd_device *USB_init();
void usb_send(uint8_t byte);
void usb_send_buffer();
#endif // __CCDCACM_H__

View File

@@ -0,0 +1,60 @@
/*
* 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);
// DMAGPIO
gpio_set_mode(DMAGPIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
DMAGPIO_PINS);
/*
// 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(8999); // 9000 pulses: 1kHz
systick_interrupt_enable();
systick_counter_enable();
}

View File

@@ -0,0 +1,65 @@
/*
* 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();
/*
* DMA to GPIO port & pins (mask)
*/
#define DMAGPIO_PORT GPIOA
#define DMAGPIO_PINS 0xff
#define DMAGPIO_TARGADDR GPIOA_ODR
/*
* 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()
#endif // __HARDWARE_INI_H__

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

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

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

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

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

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

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

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

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

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

View File

@@ -0,0 +1,90 @@
/*
* 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 "timgpio.h"
volatile uint32_t Timer = 0; // global timer (milliseconds)
usbd_device *usbd_dev;
int main(){
uint32_t Old_timer = 0;
// 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();
timgpio_init();
usb_connect(); // turn on USB
int oldusblen = 0;
while(1){
usbd_poll(usbd_dev);
if(usbdatalen != oldusblen){ // there's something in USB buffer
parse_incoming_buf(usbdatabuf, &usbdatalen);
oldusblen = usbdatalen;
}
if(transfer_complete){
P("transfered\n");
transfer_complete = 0;
}
if(Timer - Old_timer > 999){ // one-second cycle
Old_timer += 1000;
}else if(Timer < Old_timer){ // Timer overflow
Old_timer = 0;
}
}
}
/**
* SysTick interrupt: increment global time & send data buffer through USB
*/
void sys_tick_handler(){
Timer++;
usbd_poll(usbd_dev);
usb_send_buffer();
}
// pause function, delay in ms
void Delay(uint16_t _U_ time){
uint32_t waitto = Timer + time;
while(Timer < waitto);
}
/**
* print current time in milliseconds: 4 bytes for ovrvlow + 4 bytes for time
* with ' ' as delimeter
*/
void print_time(){
print_int(Timer);
}

View File

@@ -0,0 +1,53 @@
/*
* 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 <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/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/dma.h>
#include <libopencm3/stm32/spi.h>
#include <libopencm3/stm32/timer.h>
#include "sync.h" // mutexes
#include "user_proto.h"
#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__

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

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

Binary file not shown.

View File

@@ -0,0 +1,61 @@
/*
* timgpio.c
*
* Copyright 2016 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 "timgpio.h"
#include "user_proto.h"
int transfer_complete = 0;
static uint8_t addr[128];
static uint32_t len = 0, curidx = 0;
void timgpio_init(){
// init TIM2 & DMA1ch2 (TIM2UP)
rcc_periph_clock_enable(RCC_TIM2);
rcc_periph_clock_enable(RCC_DMA1);
timer_reset(TIM2);
// timer have frequency of 1MHz
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
// 72MHz main freq, 2MHz for timer
TIM2_PSC = 0;
TIM2_ARR = 35;
TIM2_DIER = TIM_DIER_UDE | TIM_DIER_UIE;
nvic_enable_irq(NVIC_TIM2_IRQ);
}
void tim2_isr(){
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
GPIOA_ODR = addr[curidx];
if(++curidx >= len){
TIM2_CR1 &= ~TIM_CR1_CEN;
transfer_complete = 1;
}
TIM2_SR = 0;
}
}
void timgpio_transfer(uint8_t *databuf, uint32_t length){
transfer_complete = 0;
memcpy(addr, databuf, length);
len = length;
curidx = 0;
TIM2_CR1 |= TIM_CR1_CEN; // run timer
}

Some files were not shown because too many files have changed in this diff Show More