mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
add CDC for STM32F042 (not working yet)
This commit is contained in:
parent
c40e239b19
commit
6df3b9f5c2
@ -11,3 +11,4 @@ This directory contains examples for F0 without any library
|
|||||||
- uart - USART over DMA with hardware end-of-string detection
|
- uart - USART over DMA with hardware end-of-string detection
|
||||||
- uart_blink - code for STM32F030F4, echo data on USART1 and blink LEDS on PA4 and PA5
|
- uart_blink - code for STM32F030F4, echo data on USART1 and blink LEDS on PA4 and PA5
|
||||||
- uart_nucleo - USART over DMA for STM32F042-nucleo
|
- uart_nucleo - USART over DMA for STM32F042-nucleo
|
||||||
|
- usbcdc - CDC for STM32F042 (emulation of ch340)
|
||||||
|
|||||||
149
F0-nolib/usbcdc/Makefile
Normal file
149
F0-nolib/usbcdc/Makefile
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
BINARY = usbcan
|
||||||
|
BOOTPORT ?= /dev/ttyUSB0
|
||||||
|
BOOTSPEED ?= 57600
|
||||||
|
# MCU FAMILY
|
||||||
|
FAMILY = F0
|
||||||
|
# MCU code
|
||||||
|
MCU = F042x6
|
||||||
|
# hardware definitions
|
||||||
|
DEFS += -DUSARTNUM=1
|
||||||
|
#DEFS += -DCHECK_TMOUT
|
||||||
|
DEFS += -DEBUG
|
||||||
|
# change this linking script depending on particular MCU model,
|
||||||
|
# for example, if you have STM32F103VBT6, you should write:
|
||||||
|
LDSCRIPT = ld/stm32f042k.ld
|
||||||
|
|
||||||
|
INDEPENDENT_HEADERS=
|
||||||
|
|
||||||
|
FP_FLAGS ?= -msoft-float
|
||||||
|
ASM_FLAGS = -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0
|
||||||
|
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Executables
|
||||||
|
OPREFIX ?= /opt/bin/arm-none-eabi
|
||||||
|
#PREFIX ?= /usr/x86_64-pc-linux-gnu/arm-none-eabi/gcc-bin/7.3.0/arm-none-eabi
|
||||||
|
PREFIX ?= $(OPREFIX)
|
||||||
|
|
||||||
|
RM := rm -f
|
||||||
|
RMDIR := rmdir
|
||||||
|
CC := $(PREFIX)-gcc
|
||||||
|
LD := $(PREFIX)-gcc
|
||||||
|
AR := $(PREFIX)-ar
|
||||||
|
AS := $(PREFIX)-as
|
||||||
|
OBJCOPY := $(OPREFIX)-objcopy
|
||||||
|
OBJDUMP := $(OPREFIX)-objdump
|
||||||
|
GDB := $(OPREFIX)-gdb
|
||||||
|
STFLASH := $(shell which st-flash)
|
||||||
|
STBOOT := $(shell which stm32flash)
|
||||||
|
DFUUTIL := $(shell which dfu-util)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Source files
|
||||||
|
OBJDIR = mk
|
||||||
|
LDSCRIPT ?= $(BINARY).ld
|
||||||
|
SRC := $(wildcard *.c)
|
||||||
|
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||||
|
STARTUP = $(OBJDIR)/startup.o
|
||||||
|
OBJS += $(STARTUP)
|
||||||
|
DEPS := $(OBJS:.o=.d)
|
||||||
|
|
||||||
|
INC_DIR ?= ../inc
|
||||||
|
|
||||||
|
INCLUDE := -I$(INC_DIR)/F0 -I$(INC_DIR)/cm
|
||||||
|
LIB_DIR := $(INC_DIR)/ld
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# C flags
|
||||||
|
CFLAGS += -O2 -g -MD -D__thumb2__=1
|
||||||
|
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
|
||||||
|
CFLAGS += -Wredundant-decls $(INCLUDE)
|
||||||
|
# -Wmissing-prototypes -Wstrict-prototypes
|
||||||
|
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Linker flags
|
||||||
|
LDFLAGS += --static -nostartfiles
|
||||||
|
#--specs=nano.specs
|
||||||
|
LDFLAGS += -L$(LIB_DIR)
|
||||||
|
LDFLAGS += -T$(LDSCRIPT)
|
||||||
|
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
|
||||||
|
LDFLAGS += -Wl,--gc-sections
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Used libraries
|
||||||
|
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||||
|
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||||
|
|
||||||
|
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
|
||||||
|
|
||||||
|
#.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 list
|
||||||
|
|
||||||
|
elf: $(ELF)
|
||||||
|
bin: $(BIN)
|
||||||
|
hex: $(HEX)
|
||||||
|
list: $(LIST)
|
||||||
|
|
||||||
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
|
-include $(DEPS)
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir $(OBJDIR)
|
||||||
|
|
||||||
|
$(STARTUP): $(INC_DIR)/startup/vector.c
|
||||||
|
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
@echo " CC $<"
|
||||||
|
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
#$(OBJDIR)/%.d: %.c $(OBJDIR)
|
||||||
|
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
|
||||||
|
|
||||||
|
$(BIN): $(ELF)
|
||||||
|
@echo " OBJCOPY $(BIN)"
|
||||||
|
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||||
|
|
||||||
|
$(HEX): $(ELF)
|
||||||
|
@echo " OBJCOPY $(HEX)"
|
||||||
|
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||||
|
|
||||||
|
$(LIST): $(ELF)
|
||||||
|
@echo " OBJDUMP $(LIST)"
|
||||||
|
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||||
|
|
||||||
|
$(ELF): $(OBJDIR) $(OBJS)
|
||||||
|
@echo " LD $(ELF)"
|
||||||
|
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo " CLEAN"
|
||||||
|
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map *.d
|
||||||
|
@rmdir $(OBJDIR) 2>/dev/null || true
|
||||||
|
|
||||||
|
dfuboot: $(BIN)
|
||||||
|
@echo " LOAD $(BIN) THROUGH DFU"
|
||||||
|
$(DFUUTIL) -a0 -D $(BIN) -s 0x08000000
|
||||||
|
|
||||||
|
flash: $(BIN)
|
||||||
|
@echo " FLASH $(BIN)"
|
||||||
|
$(STFLASH) write $(BIN) 0x8000000
|
||||||
|
|
||||||
|
boot: $(BIN)
|
||||||
|
@echo " LOAD $(BIN) through bootloader"
|
||||||
|
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||||
|
|
||||||
|
gentags:
|
||||||
|
CFLAGS="$(CFLAGS) $(DEFS)" geany -g $(BINARY).c.tags *[hc] 2>/dev/null
|
||||||
|
|
||||||
|
.PHONY: clean flash boot gentags
|
||||||
5
F0-nolib/usbcdc/Readme.md
Normal file
5
F0-nolib/usbcdc/Readme.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Simple code for CAN/USB development board
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
USB: https://github.com/majbthrd/CDCHIDwidget/blob/master/src/main.c
|
||||||
335
F0-nolib/usbcdc/can.c
Normal file
335
F0-nolib/usbcdc/can.c
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* can.c
|
||||||
|
*
|
||||||
|
* Copyright 2018 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 <string.h> // memcpy
|
||||||
|
#include "can.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "usart.h"
|
||||||
|
|
||||||
|
#define CMD_TOGGLE (0xDA)
|
||||||
|
#define CMD_BCAST (0xAD)
|
||||||
|
#define CAN_ID_MASK (0x7F8)
|
||||||
|
#define CAN_ID_PREFIX (0xAAA)
|
||||||
|
#define TARG_ID (CAN_ID_PREFIX & CAN_ID_MASK)
|
||||||
|
#define BCAST_ID (0x7F7)
|
||||||
|
|
||||||
|
#define CAN_FLAG_GOTDUMMY (1)
|
||||||
|
// incoming message buffer size
|
||||||
|
#define CAN_INMESSAGE_SIZE (6)
|
||||||
|
|
||||||
|
extern volatile uint32_t Tms;
|
||||||
|
|
||||||
|
// circular buffer for received messages
|
||||||
|
static CAN_message messages[CAN_INMESSAGE_SIZE];
|
||||||
|
static uint8_t first_free_idx = 0; // index of first empty cell
|
||||||
|
static int8_t first_nonfree_idx = -1; // index of first data cell
|
||||||
|
|
||||||
|
static uint16_t CANID = 0xFFFF;
|
||||||
|
static uint32_t last_err_code = 0;
|
||||||
|
static CAN_status can_status = CAN_STOP;
|
||||||
|
|
||||||
|
static void can_process_fifo(uint8_t fifo_num);
|
||||||
|
|
||||||
|
CAN_status CAN_get_status(){
|
||||||
|
CAN_status st = can_status;
|
||||||
|
// give overrun message only once
|
||||||
|
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
// push next message into buffer; return 1 if buffer overfull
|
||||||
|
static int CAN_messagebuf_push(CAN_message *msg){
|
||||||
|
MSG("Try to push\n");
|
||||||
|
if(first_free_idx == first_nonfree_idx) return 1; // no free space
|
||||||
|
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
|
||||||
|
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
|
||||||
|
// need to roll?
|
||||||
|
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("1st free: "); usart_putchar('0' + first_free_idx); newline();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pop message from buffer
|
||||||
|
CAN_message *CAN_messagebuf_pop(){
|
||||||
|
if(first_nonfree_idx < 0) return NULL;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("read from idx "); usart_putchar('0' + first_nonfree_idx); newline();
|
||||||
|
#endif
|
||||||
|
CAN_message *msg = &messages[first_nonfree_idx++];
|
||||||
|
if(first_nonfree_idx == CAN_INMESSAGE_SIZE) first_nonfree_idx = 0;
|
||||||
|
if(first_nonfree_idx == first_free_idx){ // buffer is empty - refresh it
|
||||||
|
first_nonfree_idx = -1;
|
||||||
|
first_free_idx = 0;
|
||||||
|
MSG("refresh buffer\n");
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get CAN address data from GPIO pins
|
||||||
|
void readCANID(){
|
||||||
|
uint8_t CAN_addr = READ_CAN_INV_ADDR();
|
||||||
|
CAN_addr = ~CAN_addr & 0x7;
|
||||||
|
CANID = (CAN_ID_PREFIX & CAN_ID_MASK) | CAN_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getCANID(){
|
||||||
|
return CANID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN_reinit(){
|
||||||
|
readCANID();
|
||||||
|
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
|
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
||||||
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
||||||
|
CAN_setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN_setup(){
|
||||||
|
if(CANID == 0xFFFF) readCANID();
|
||||||
|
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
|
||||||
|
/* (1) Select AF mode (10) on PB8 and PB9 */
|
||||||
|
/* (2) AF4 for CAN signals */
|
||||||
|
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER9))
|
||||||
|
| (GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF); /* (1) */
|
||||||
|
GPIOB->AFR[1] = (GPIOB->AFR[1] &~ (GPIO_AFRH_AFRH0 | GPIO_AFRH_AFRH1))\
|
||||||
|
| (4 << (0 * 4)) | (4 << (1 * 4)); /* (2) */
|
||||||
|
/* Enable the peripheral clock CAN */
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_CANEN;
|
||||||
|
/* Configure CAN */
|
||||||
|
/* (1) Enter CAN init mode to write the configuration */
|
||||||
|
/* (2) Wait the init mode entering */
|
||||||
|
/* (3) Exit sleep mode */
|
||||||
|
/* (4) Loopback mode, set timing to 100kb/s: BS1 = 4, BS2 = 3, prescaler = 60 */
|
||||||
|
/* (5) Leave init mode */
|
||||||
|
/* (6) Wait the init mode leaving */
|
||||||
|
/* (7) Enter filter init mode, (16-bit + mask, filter 0 for FIFO 0) */
|
||||||
|
/* (8) Acivate filter 0 for two IDs */
|
||||||
|
/* (9) Identifier list mode */
|
||||||
|
/* (10) Set the Id list */
|
||||||
|
/* (12) Leave filter init */
|
||||||
|
/* (13) Set error interrupts enable */
|
||||||
|
CAN->MCR |= CAN_MCR_INRQ; /* (1) */
|
||||||
|
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK) /* (2) */
|
||||||
|
{
|
||||||
|
/* add time out here for a robust application */
|
||||||
|
}
|
||||||
|
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||||
|
CAN->MCR |= CAN_MCR_ABOM;
|
||||||
|
|
||||||
|
CAN->BTR |= 2 << 20 | 3 << 16 | 59 << 0; /* (4) */
|
||||||
|
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
|
||||||
|
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) /* (6) */
|
||||||
|
{
|
||||||
|
/* add time out here for a robust application */
|
||||||
|
}
|
||||||
|
CAN->FMR = CAN_FMR_FINIT; /* (7) */
|
||||||
|
CAN->FA1R = CAN_FA1R_FACT0; /* (8) */
|
||||||
|
CAN->FM1R = CAN_FM1R_FBM0; /* (9) */
|
||||||
|
CAN->sFilterRegister[0].FR1 = CANID << 5 | ((BCAST_ID << 5) << 16); /* (10) */
|
||||||
|
|
||||||
|
CAN->FMR &=~ CAN_FMR_FINIT; /* (12) */
|
||||||
|
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1; /* (13) */
|
||||||
|
|
||||||
|
/* Configure IT */
|
||||||
|
/* (14) Set priority for CAN_IRQn */
|
||||||
|
/* (15) Enable CAN_IRQn */
|
||||||
|
NVIC_SetPriority(CEC_CAN_IRQn, 0); /* (14) */
|
||||||
|
NVIC_EnableIRQ(CEC_CAN_IRQn); /* (15) */
|
||||||
|
can_status = CAN_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void can_proc(){
|
||||||
|
if(last_err_code){
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("Error, ESR=");
|
||||||
|
printu(last_err_code);
|
||||||
|
newline();
|
||||||
|
#endif
|
||||||
|
last_err_code = 0;
|
||||||
|
}
|
||||||
|
// check for messages in FIFO0 & FIFO1
|
||||||
|
if(CAN->RF0R & CAN_RF0R_FMP0){
|
||||||
|
can_process_fifo(0);
|
||||||
|
}
|
||||||
|
if(CAN->RF1R & CAN_RF1R_FMP1){
|
||||||
|
can_process_fifo(1);
|
||||||
|
}
|
||||||
|
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
|
||||||
|
MSG("bus-off, restarting\n");
|
||||||
|
// request abort for all mailboxes
|
||||||
|
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
|
// reset CAN bus
|
||||||
|
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
||||||
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
||||||
|
CAN_setup();
|
||||||
|
}
|
||||||
|
LED_off(LED1);
|
||||||
|
#ifdef EBUG
|
||||||
|
static uint32_t esr, msr, tsr;
|
||||||
|
uint32_t msr_now = CAN->MSR & 0xf;
|
||||||
|
if(esr != CAN->ESR || msr != msr_now || tsr != CAN->TSR){
|
||||||
|
MSG("Timestamp: ");
|
||||||
|
printu(Tms);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
if((CAN->ESR) != esr){
|
||||||
|
usart_putchar(((CAN->ESR & CAN_ESR_BOFF) != 0) + '0');
|
||||||
|
esr = CAN->ESR;
|
||||||
|
MSG("CAN->ESR: ");
|
||||||
|
printuhex(esr); newline();
|
||||||
|
}
|
||||||
|
if(msr_now != msr){
|
||||||
|
msr = msr_now;
|
||||||
|
MSG("CAN->MSR & 0xf: ");
|
||||||
|
printuhex(msr); newline();
|
||||||
|
}
|
||||||
|
if(CAN->TSR != tsr){
|
||||||
|
tsr = CAN->TSR;
|
||||||
|
MSG("CAN->TSR: ");
|
||||||
|
printuhex(tsr); newline();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
|
||||||
|
uint8_t mailbox = 0;
|
||||||
|
// check first free mailbox
|
||||||
|
if(CAN->TSR & (CAN_TSR_TME)){
|
||||||
|
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("select "); usart_putchar('0'+mailbox); SEND(" mailbox\n");
|
||||||
|
#endif
|
||||||
|
}else{ // no free mailboxes
|
||||||
|
return CAN_BUSY;
|
||||||
|
}
|
||||||
|
CAN_TxMailBox_TypeDef *box = &CAN->sTxMailBox[mailbox];
|
||||||
|
uint32_t lb = 0, hb = 0;
|
||||||
|
switch(len){
|
||||||
|
case 8:
|
||||||
|
hb |= (uint32_t)msg[7] << 24;
|
||||||
|
case 7:
|
||||||
|
hb |= (uint32_t)msg[6] << 16;
|
||||||
|
case 6:
|
||||||
|
hb |= (uint32_t)msg[5] << 8;
|
||||||
|
case 5:
|
||||||
|
hb |= (uint32_t)msg[4];
|
||||||
|
case 4:
|
||||||
|
lb |= (uint32_t)msg[3] << 24;
|
||||||
|
case 3:
|
||||||
|
lb |= (uint32_t)msg[2] << 16;
|
||||||
|
case 2:
|
||||||
|
lb |= (uint32_t)msg[1] << 8;
|
||||||
|
default:
|
||||||
|
lb |= (uint32_t)msg[0];
|
||||||
|
}
|
||||||
|
box->TDLR = lb;
|
||||||
|
box->TDHR = hb;
|
||||||
|
box->TDTR = len;
|
||||||
|
box->TIR = (target_id & 0x7FF) << 21 | CAN_TI0R_TXRQ;
|
||||||
|
return CAN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void can_send_dummy(){
|
||||||
|
uint8_t msg = CMD_TOGGLE;
|
||||||
|
if(CAN_OK != can_send(&msg, 1, TARG_ID)) SEND("Bus busy!\n");
|
||||||
|
MSG("CAN->MSR: ");
|
||||||
|
printuhex(CAN->MSR); newline();
|
||||||
|
MSG("CAN->TSR: ");
|
||||||
|
printuhex(CAN->TSR); newline();
|
||||||
|
MSG("CAN->ESR: ");
|
||||||
|
printuhex(CAN->ESR); newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
void can_send_broadcast(){
|
||||||
|
uint8_t msg = CMD_BCAST;
|
||||||
|
if(CAN_OK != can_send(&msg, 1, BCAST_ID)) SEND("Bus busy!\n");
|
||||||
|
MSG("Broadcast message sent\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void can_process_fifo(uint8_t fifo_num){
|
||||||
|
if(fifo_num > 1) return;
|
||||||
|
LED_on(LED1); // Toggle LED1
|
||||||
|
CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num];
|
||||||
|
volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R;
|
||||||
|
MSG("Receive, RDTR=");
|
||||||
|
#ifdef EBUG
|
||||||
|
printuhex(box->RDTR);
|
||||||
|
newline();
|
||||||
|
#endif
|
||||||
|
// read all
|
||||||
|
while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending
|
||||||
|
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
|
||||||
|
/* TODO: check filter match index if more than one ID can receive */
|
||||||
|
CAN_message msg;
|
||||||
|
uint8_t *dat = msg.data;
|
||||||
|
uint8_t len = box->RDTR & 0x7;
|
||||||
|
msg.length = len;
|
||||||
|
if(len){ // message can be without data
|
||||||
|
uint32_t hb = box->RDHR, lb = box->RDLR;
|
||||||
|
switch(len){
|
||||||
|
case 8:
|
||||||
|
dat[7] = hb>>24;
|
||||||
|
case 7:
|
||||||
|
dat[6] = (hb>>16) & 0xff;
|
||||||
|
case 6:
|
||||||
|
dat[5] = (hb>>8) & 0xff;
|
||||||
|
case 5:
|
||||||
|
dat[4] = hb & 0xff;
|
||||||
|
case 4:
|
||||||
|
dat[3] = lb>>24;
|
||||||
|
case 3:
|
||||||
|
dat[2] = (lb>>16) & 0xff;
|
||||||
|
case 2:
|
||||||
|
dat[1] = (lb>>8) & 0xff;
|
||||||
|
case 1:
|
||||||
|
dat[0] = lb & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
|
||||||
|
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
|
||||||
|
}
|
||||||
|
if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cec_can_isr(){
|
||||||
|
if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun
|
||||||
|
CAN->RF0R &= ~CAN_RF0R_FOVR0;
|
||||||
|
can_status = CAN_FIFO_OVERRUN;
|
||||||
|
}
|
||||||
|
if(CAN->RF1R & CAN_RF1R_FOVR1){
|
||||||
|
CAN->RF1R &= ~CAN_RF1R_FOVR1;
|
||||||
|
can_status = CAN_FIFO_OVERRUN;
|
||||||
|
}
|
||||||
|
#ifdef EBUG
|
||||||
|
if(can_status == CAN_FIFO_OVERRUN) MSG("fifo 0 overrun\n");
|
||||||
|
#endif
|
||||||
|
if(CAN->MSR & CAN_MSR_ERRI){ // Error
|
||||||
|
CAN->MSR &= ~CAN_MSR_ERRI;
|
||||||
|
// request abort for problem mailbox
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR0) CAN->TSR |= CAN_TSR_ABRQ0;
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR1) CAN->TSR |= CAN_TSR_ABRQ1;
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR2) CAN->TSR |= CAN_TSR_ABRQ2;
|
||||||
|
last_err_code = CAN->ESR;
|
||||||
|
}
|
||||||
|
}
|
||||||
56
F0-nolib/usbcdc/can.h
Normal file
56
F0-nolib/usbcdc/can.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* can.h
|
||||||
|
*
|
||||||
|
* Copyright 2018 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 __CAN_H__
|
||||||
|
#define __CAN_H__
|
||||||
|
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
uint8_t data[8];
|
||||||
|
uint8_t length;
|
||||||
|
} CAN_message;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
CAN_STOP,
|
||||||
|
CAN_READY,
|
||||||
|
CAN_BUSY,
|
||||||
|
CAN_OK,
|
||||||
|
CAN_FIFO_OVERRUN
|
||||||
|
} CAN_status;
|
||||||
|
|
||||||
|
CAN_status CAN_get_status();
|
||||||
|
|
||||||
|
void readCANID();
|
||||||
|
uint16_t getCANID();
|
||||||
|
|
||||||
|
void CAN_reinit();
|
||||||
|
void CAN_setup();
|
||||||
|
|
||||||
|
void can_send_dummy();
|
||||||
|
void can_send_broadcast();
|
||||||
|
void can_proc();
|
||||||
|
|
||||||
|
CAN_message *CAN_messagebuf_pop();
|
||||||
|
|
||||||
|
#endif // __CAN_H__
|
||||||
4433
F0-nolib/usbcdc/canbus.c.tags
Normal file
4433
F0-nolib/usbcdc/canbus.c.tags
Normal file
File diff suppressed because it is too large
Load Diff
43
F0-nolib/usbcdc/hardware.c
Normal file
43
F0-nolib/usbcdc/hardware.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* hardware.c - hardware-dependent macros & functions
|
||||||
|
*
|
||||||
|
* Copyright 2018 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 "hardware.h"
|
||||||
|
#include "usart.h"
|
||||||
|
|
||||||
|
void gpio_setup(void){
|
||||||
|
// here we turn on clocking for all periph.
|
||||||
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_DMAEN;
|
||||||
|
// Set LEDS (PC13/14) as output
|
||||||
|
GPIOC->MODER = (GPIOC->MODER & ~(GPIO_MODER_MODER13 | GPIO_MODER_MODER14)
|
||||||
|
) |
|
||||||
|
GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O;
|
||||||
|
// PB14(0), PB15(1), PA8(2) - CAN address, pullup inputs
|
||||||
|
GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPDR8)
|
||||||
|
) |
|
||||||
|
GPIO_PUPDR_PUPDR8_0;
|
||||||
|
GPIOB->PUPDR = (GPIOB->PUPDR & ~(GPIO_PUPDR_PUPDR14 | GPIO_PUPDR_PUPDR15)
|
||||||
|
) |
|
||||||
|
GPIO_PUPDR_PUPDR14_0 | GPIO_PUPDR_PUPDR15_0;
|
||||||
|
pin_set(LED0_port, LED0_pin); // clear LEDs
|
||||||
|
pin_set(LED1_port, LED1_pin);
|
||||||
|
}
|
||||||
54
F0-nolib/usbcdc/hardware.h
Normal file
54
F0-nolib/usbcdc/hardware.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* hardware.h
|
||||||
|
*
|
||||||
|
* Copyright 2018 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_H__
|
||||||
|
#define __HARDWARE_H__
|
||||||
|
|
||||||
|
#include "stm32f0.h"
|
||||||
|
|
||||||
|
#define CONCAT(a,b) a ## b
|
||||||
|
#define STR_HELPER(s) #s
|
||||||
|
#define STR(s) STR_HELPER(s)
|
||||||
|
|
||||||
|
#define FORMUSART(X) CONCAT(USART, X)
|
||||||
|
#define USARTX FORMUSART(USARTNUM)
|
||||||
|
|
||||||
|
// LEDS: 0 - PC13, 1 - PC14
|
||||||
|
// LED0
|
||||||
|
#define LED0_port GPIOC
|
||||||
|
#define LED0_pin (1<<13)
|
||||||
|
// LED1
|
||||||
|
#define LED1_port GPIOC
|
||||||
|
#define LED1_pin (1<<14)
|
||||||
|
|
||||||
|
#define LED_blink(x) pin_toggle(x ## _port, x ## _pin)
|
||||||
|
#define LED_on(x) pin_clear(x ## _port, x ## _pin)
|
||||||
|
#define LED_off(x) pin_set(x ## _port, x ## _pin)
|
||||||
|
|
||||||
|
|
||||||
|
// CAN address - PB14(0), PB15(1), PA8(2)
|
||||||
|
#define READ_CAN_INV_ADDR() (((GPIOA->IDR & (1<<8))>>6)|((GPIOB->IDR & (3<<14))>>14))
|
||||||
|
|
||||||
|
void gpio_setup(void);
|
||||||
|
|
||||||
|
#endif // __HARDWARE_H__
|
||||||
12
F0-nolib/usbcdc/ld/stm32f042k.ld
Normal file
12
F0-nolib/usbcdc/ld/stm32f042k.ld
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* Linker script for STM32F042x6, 32K flash, 6K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE stm32f0.ld
|
||||||
|
|
||||||
157
F0-nolib/usbcdc/main.c
Normal file
157
F0-nolib/usbcdc/main.c
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianoff <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 "hardware.h"
|
||||||
|
#include "usart.h"
|
||||||
|
#include "can.h"
|
||||||
|
#include "usb.h"
|
||||||
|
#include "usb_lib.h"
|
||||||
|
|
||||||
|
volatile uint32_t Tms = 0;
|
||||||
|
|
||||||
|
/* Called when systick fires */
|
||||||
|
void sys_tick_handler(void){
|
||||||
|
++Tms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwdg_setup(){
|
||||||
|
/* Enable the peripheral clock RTC */
|
||||||
|
/* (1) Enable the LSI (40kHz) */
|
||||||
|
/* (2) Wait while it is not ready */
|
||||||
|
RCC->CSR |= RCC_CSR_LSION; /* (1) */
|
||||||
|
while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY); /* (2) */
|
||||||
|
/* Configure IWDG */
|
||||||
|
/* (1) Activate IWDG (not needed if done in option bytes) */
|
||||||
|
/* (2) Enable write access to IWDG registers */
|
||||||
|
/* (3) Set prescaler by 64 (1.6ms for each tick) */
|
||||||
|
/* (4) Set reload value to have a rollover each 2s */
|
||||||
|
/* (5) Check if flags are reset */
|
||||||
|
/* (6) Refresh counter */
|
||||||
|
IWDG->KR = IWDG_START; /* (1) */
|
||||||
|
IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */
|
||||||
|
IWDG->PR = IWDG_PR_PR_1; /* (3) */
|
||||||
|
IWDG->RLR = 1250; /* (4) */
|
||||||
|
while(IWDG->SR); /* (5) */
|
||||||
|
IWDG->KR = IWDG_REFRESH; /* (6) */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void){
|
||||||
|
uint32_t lastT = 0;
|
||||||
|
uint8_t ctr, len;
|
||||||
|
CAN_message *can_mesg;
|
||||||
|
int L;
|
||||||
|
char *txt;
|
||||||
|
sysreset();
|
||||||
|
SysTick_Config(6000, 1);
|
||||||
|
gpio_setup();
|
||||||
|
usart_setup();
|
||||||
|
//iwdg_setup();
|
||||||
|
readCANID();
|
||||||
|
CAN_setup();
|
||||||
|
|
||||||
|
SEND("Greetings! My address is ");
|
||||||
|
printuhex(getCANID());
|
||||||
|
newline();
|
||||||
|
|
||||||
|
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
|
||||||
|
SEND("WDGRESET=1\n");
|
||||||
|
}
|
||||||
|
if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured
|
||||||
|
SEND("SOFTRESET=1\n");
|
||||||
|
}
|
||||||
|
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
||||||
|
|
||||||
|
USB_setup();
|
||||||
|
|
||||||
|
while (1){
|
||||||
|
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
||||||
|
if(lastT > Tms || Tms - lastT > 499){
|
||||||
|
LED_blink(LED0);
|
||||||
|
lastT = Tms;
|
||||||
|
}
|
||||||
|
can_proc();
|
||||||
|
usb_proc();
|
||||||
|
if(CAN_get_status() == CAN_FIFO_OVERRUN){
|
||||||
|
SEND("CAN bus fifo overrun occured!\n");
|
||||||
|
}
|
||||||
|
can_mesg = CAN_messagebuf_pop();
|
||||||
|
if(can_mesg){ // new data in buff
|
||||||
|
len = can_mesg->length;
|
||||||
|
SEND("got message, len: "); usart_putchar('0' + len);
|
||||||
|
SEND(", data: ");
|
||||||
|
for(ctr = 0; ctr < len; ++ctr){
|
||||||
|
printuhex(can_mesg->data[ctr]);
|
||||||
|
usart_putchar(' ');
|
||||||
|
}
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
if(usartrx()){ // usart1 received data, store in in buffer
|
||||||
|
L = usart_getline(&txt);
|
||||||
|
char _1st = txt[0];
|
||||||
|
if(L == 2 && txt[1] == '\n'){
|
||||||
|
L = 0;
|
||||||
|
switch(_1st){
|
||||||
|
case 'B':
|
||||||
|
can_send_broadcast();
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
can_send_dummy();
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
SEND("Can address: ");
|
||||||
|
printuhex(getCANID());
|
||||||
|
newline();
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
SEND("Soft reset\n");
|
||||||
|
NVIC_SystemReset();
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
CAN_reinit();
|
||||||
|
SEND("Can address: ");
|
||||||
|
printuhex(getCANID());
|
||||||
|
newline();
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
SEND("Wait for reboot\n");
|
||||||
|
while(1){nop();};
|
||||||
|
break;
|
||||||
|
default: // help
|
||||||
|
SEND(
|
||||||
|
"'B' - send broadcast dummy byte\n"
|
||||||
|
"'C' - send dummy byte over CAN\n"
|
||||||
|
"'G' - get CAN address\n"
|
||||||
|
"'R' - software reset\n"
|
||||||
|
"'S' - reinit CAN (with new address)\n"
|
||||||
|
"'W' - test watchdog\n"
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(L){ // text waits for sending
|
||||||
|
while(LINE_BUSY == usart_send(txt, L));
|
||||||
|
L = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
252
F0-nolib/usbcdc/usart.c
Normal file
252
F0-nolib/usbcdc/usart.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/*us
|
||||||
|
* usart.c
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianoff <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 "stm32f0.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "usart.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
extern volatile uint32_t Tms;
|
||||||
|
static int datalen[2] = {0,0}; // received data line length (including '\n')
|
||||||
|
|
||||||
|
volatile int linerdy = 0, // received data ready
|
||||||
|
dlen = 0, // length of data (including '\n') in current buffer
|
||||||
|
bufovr = 0, // input buffer overfull
|
||||||
|
txrdy = 1 // transmission done
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
int rbufno = 0; // current rbuf number
|
||||||
|
static char rbuf[UARTBUFSZ][2], tbuf[UARTBUFSZ]; // receive & transmit buffers
|
||||||
|
static char *recvdata = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return length of received data (without trailing zero
|
||||||
|
*/
|
||||||
|
int usart_getline(char **line){
|
||||||
|
if(bufovr){
|
||||||
|
bufovr = 0;
|
||||||
|
linerdy = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*line = recvdata;
|
||||||
|
linerdy = 0;
|
||||||
|
return dlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
TXstatus usart_send(const char *str, int len){
|
||||||
|
if(!txrdy) return LINE_BUSY;
|
||||||
|
if(len > UARTBUFSZ) return STR_TOO_LONG;
|
||||||
|
txrdy = 0;
|
||||||
|
memcpy(tbuf, str, len);
|
||||||
|
#if USARTNUM == 2
|
||||||
|
DMA1_Channel4->CCR &= ~DMA_CCR_EN;
|
||||||
|
DMA1_Channel4->CNDTR = len;
|
||||||
|
DMA1_Channel4->CCR |= DMA_CCR_EN; // start transmission
|
||||||
|
#elif USARTNUM == 1
|
||||||
|
DMA1_Channel2->CCR &= ~DMA_CCR_EN;
|
||||||
|
DMA1_Channel2->CNDTR = len;
|
||||||
|
DMA1_Channel2->CCR |= DMA_CCR_EN;
|
||||||
|
#else
|
||||||
|
#error "Not implemented"
|
||||||
|
#endif
|
||||||
|
return ALL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
TXstatus usart_send_blocking(const char *str, int len){
|
||||||
|
while(!txrdy);
|
||||||
|
int i;
|
||||||
|
bufovr = 0;
|
||||||
|
for(i = 0; i < len; ++i){
|
||||||
|
USARTX->TDR = *str++;
|
||||||
|
while(!(USARTX->ISR & USART_ISR_TXE));
|
||||||
|
}
|
||||||
|
return ALL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usart_putchar(const char ch){
|
||||||
|
while(!txrdy);
|
||||||
|
USARTX->TDR = ch;
|
||||||
|
while(!(USARTX->ISR & USART_ISR_TXE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void newline(){
|
||||||
|
while(!txrdy);
|
||||||
|
USARTX->TDR = '\n';
|
||||||
|
while(!(USARTX->ISR & USART_ISR_TXE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void usart_setup(){
|
||||||
|
// Nucleo's USART2 connected to VCP proxy of st-link
|
||||||
|
#if USARTNUM == 2
|
||||||
|
// setup pins: PA2 (Tx - AF1), PA15 (Rx - AF1)
|
||||||
|
// AF mode (AF1)
|
||||||
|
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER2|GPIO_MODER_MODER15))\
|
||||||
|
| (GPIO_MODER_MODER2_AF | GPIO_MODER_MODER15_AF);
|
||||||
|
GPIOA->AFR[0] = (GPIOA->AFR[0] &~GPIO_AFRH_AFRH2) | 1 << (2 * 4); // PA2
|
||||||
|
GPIOA->AFR[1] = (GPIOA->AFR[1] &~GPIO_AFRH_AFRH7) | 1 << (7 * 4); // PA15
|
||||||
|
// DMA: Tx - Ch4
|
||||||
|
DMA1_Channel4->CPAR = (uint32_t) &USART2->TDR; // periph
|
||||||
|
DMA1_Channel4->CMAR = (uint32_t) tbuf; // mem
|
||||||
|
DMA1_Channel4->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
|
||||||
|
// Tx CNDTR set @ each transmission due to data size
|
||||||
|
NVIC_SetPriority(DMA1_Channel4_5_IRQn, 3);
|
||||||
|
NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
|
||||||
|
NVIC_SetPriority(USART2_IRQn, 0);
|
||||||
|
// setup usart2
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // clock
|
||||||
|
// oversampling by16, 115200bps (fck=48mHz)
|
||||||
|
//USART2_BRR = 0x1a1; // 48000000 / 115200
|
||||||
|
USART2->BRR = 480000 / 1152;
|
||||||
|
USART2->CR3 = USART_CR3_DMAT; // enable DMA Tx
|
||||||
|
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
|
||||||
|
while(!(USART2->ISR & USART_ISR_TC)); // polling idle frame Transmission
|
||||||
|
USART2->ICR |= USART_ICR_TCCF; // clear TC flag
|
||||||
|
USART2->CR1 |= USART_CR1_RXNEIE;
|
||||||
|
NVIC_EnableIRQ(USART2_IRQn);
|
||||||
|
// USART1 of main board
|
||||||
|
#elif USARTNUM == 1
|
||||||
|
// PA9 - Tx, PA10 - Rx (AF1)
|
||||||
|
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10))\
|
||||||
|
| (GPIO_MODER_MODER9_AF | GPIO_MODER_MODER10_AF);
|
||||||
|
GPIOA->AFR[1] = (GPIOA->AFR[1] & ~(GPIO_AFRH_AFRH1 | GPIO_AFRH_AFRH2)) |
|
||||||
|
1 << (1 * 4) | 1 << (2 * 4); // PA9, PA10
|
||||||
|
// USART1 Tx DMA - Channel2 (default value in SYSCFG_CFGR1)
|
||||||
|
DMA1_Channel2->CPAR = (uint32_t) &USART1->TDR; // periph
|
||||||
|
DMA1_Channel2->CMAR = (uint32_t) tbuf; // mem
|
||||||
|
DMA1_Channel2->CCR |= DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE; // 8bit, mem++, mem->per, transcompl irq
|
||||||
|
// Tx CNDTR set @ each transmission due to data size
|
||||||
|
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3);
|
||||||
|
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||||
|
NVIC_SetPriority(USART1_IRQn, 0);
|
||||||
|
// setup usart1
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||||
|
USART1->BRR = 480000 / 1152;
|
||||||
|
USART1->CR3 = USART_CR3_DMAT; // enable DMA Tx
|
||||||
|
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
|
||||||
|
while(!(USART1->ISR & USART_ISR_TC)); // polling idle frame Transmission
|
||||||
|
USART1->ICR |= USART_ICR_TCCF; // clear TC flag
|
||||||
|
USART1->CR1 |= USART_CR1_RXNEIE;
|
||||||
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
|
#else
|
||||||
|
#error "Not implemented"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USARTNUM == 2
|
||||||
|
void usart2_isr(){
|
||||||
|
// USART1
|
||||||
|
#elif USARTNUM == 1
|
||||||
|
void usart1_isr(){
|
||||||
|
#else
|
||||||
|
#error "Not implemented"
|
||||||
|
#endif
|
||||||
|
#ifdef CHECK_TMOUT
|
||||||
|
static uint32_t tmout = 0;
|
||||||
|
#endif
|
||||||
|
if(USARTX->ISR & USART_ISR_RXNE){ // RX not emty - receive next char
|
||||||
|
#ifdef CHECK_TMOUT
|
||||||
|
if(tmout && Tms >= tmout){ // set overflow flag
|
||||||
|
bufovr = 1;
|
||||||
|
datalen[rbufno] = 0;
|
||||||
|
}
|
||||||
|
tmout = Tms + TIMEOUT_MS;
|
||||||
|
if(!tmout) tmout = 1; // prevent 0
|
||||||
|
#endif
|
||||||
|
// read RDR clears flag
|
||||||
|
uint8_t rb = USARTX->RDR;
|
||||||
|
if(datalen[rbufno] < UARTBUFSZ){ // put next char into buf
|
||||||
|
rbuf[rbufno][datalen[rbufno]++] = rb;
|
||||||
|
if(rb == '\n'){ // got newline - line ready
|
||||||
|
linerdy = 1;
|
||||||
|
dlen = datalen[rbufno];
|
||||||
|
recvdata = rbuf[rbufno];
|
||||||
|
// prepare other buffer
|
||||||
|
rbufno = !rbufno;
|
||||||
|
datalen[rbufno] = 0;
|
||||||
|
#ifdef CHECK_TMOUT
|
||||||
|
// clear timeout at line end
|
||||||
|
tmout = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}else{ // buffer overrun
|
||||||
|
bufovr = 1;
|
||||||
|
datalen[rbufno] = 0;
|
||||||
|
#ifdef CHECK_TMOUT
|
||||||
|
tmout = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print 32bit unsigned int
|
||||||
|
void printu(uint32_t val){
|
||||||
|
char bufa[11], bufb[10];
|
||||||
|
int l = 0, bpos = 0;
|
||||||
|
if(!val){
|
||||||
|
bufa[0] = '0';
|
||||||
|
l = 1;
|
||||||
|
}else{
|
||||||
|
while(val){
|
||||||
|
bufb[l++] = val % 10 + '0';
|
||||||
|
val /= 10;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
bpos += l;
|
||||||
|
for(i = 0; i < l; ++i){
|
||||||
|
bufa[--bpos] = bufb[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(LINE_BUSY == usart_send_blocking(bufa, l+bpos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// print 32bit unsigned int as hex
|
||||||
|
void printuhex(uint32_t val){
|
||||||
|
SEND("0x");
|
||||||
|
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||||
|
int i, j;
|
||||||
|
for(i = 0; i < 4; ++i, --ptr){
|
||||||
|
for(j = 1; j > -1; --j){
|
||||||
|
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||||
|
if(half < 10) usart_putchar(half + '0');
|
||||||
|
else usart_putchar(half - 10 + 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USARTNUM == 2
|
||||||
|
void dma1_channel4_5_isr(){
|
||||||
|
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
||||||
|
DMA1->IFCR |= DMA_IFCR_CTCIF4; // clear TC flag
|
||||||
|
txrdy = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// USART1
|
||||||
|
#elif USARTNUM == 1
|
||||||
|
void dma1_channel2_3_isr(){
|
||||||
|
if(DMA1->ISR & DMA_ISR_TCIF2){ // Tx
|
||||||
|
DMA1->IFCR |= DMA_IFCR_CTCIF2; // clear TC flag
|
||||||
|
txrdy = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "Not implemented"
|
||||||
|
#endif
|
||||||
63
F0-nolib/usbcdc/usart.h
Normal file
63
F0-nolib/usbcdc/usart.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* usart.h
|
||||||
|
*
|
||||||
|
* Copyright 2017 Edward V. Emelianoff <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 __USART_H__
|
||||||
|
#define __USART_H__
|
||||||
|
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
|
// input and output buffers size
|
||||||
|
#define UARTBUFSZ (64)
|
||||||
|
// timeout between data bytes
|
||||||
|
#ifndef TIMEOUT_MS
|
||||||
|
#define TIMEOUT_MS (1500)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// macro for static strings
|
||||||
|
#define SEND(str) do{}while(LINE_BUSY == usart_send_blocking(str, sizeof(str)-1))
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
|
#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0)
|
||||||
|
#else
|
||||||
|
#define MSG(str)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
ALL_OK,
|
||||||
|
LINE_BUSY,
|
||||||
|
STR_TOO_LONG
|
||||||
|
} TXstatus;
|
||||||
|
|
||||||
|
#define usartrx() (linerdy)
|
||||||
|
#define usartovr() (bufovr)
|
||||||
|
|
||||||
|
extern volatile int linerdy, bufovr, txrdy;
|
||||||
|
|
||||||
|
void usart_setup();
|
||||||
|
int usart_getline(char **line);
|
||||||
|
TXstatus usart_send(const char *str, int len);
|
||||||
|
TXstatus usart_send_blocking(const char *str, int len);
|
||||||
|
void newline();
|
||||||
|
void usart_putchar(const char ch);
|
||||||
|
void printu(uint32_t val);
|
||||||
|
void printuhex(uint32_t val);
|
||||||
|
|
||||||
|
#endif // __USART_H__
|
||||||
144
F0-nolib/usbcdc/usb.c
Normal file
144
F0-nolib/usbcdc/usb.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* usb.c
|
||||||
|
*
|
||||||
|
* Copyright 2018 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 "usb.h"
|
||||||
|
#include "usb_lib.h"
|
||||||
|
#ifdef EBUG
|
||||||
|
#include "usart.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t buffer[64];
|
||||||
|
static uint8_t len, rcvflag = 0;
|
||||||
|
|
||||||
|
static uint16_t EP1_Handler(ep_t ep){
|
||||||
|
MSG("EP1 ");
|
||||||
|
if (ep.rx_flag){ //Пришли новые данные
|
||||||
|
MSG("read");
|
||||||
|
EP_Read(1, buffer);
|
||||||
|
EP_WriteIRQ(1, buffer, ep.rx_cnt);
|
||||||
|
ep.status = SET_VALID_TX(ep.status); //TX
|
||||||
|
ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK
|
||||||
|
} else
|
||||||
|
if (ep.tx_flag){ //Данные успешно переданы
|
||||||
|
MSG("write");
|
||||||
|
ep.status = SET_VALID_RX(ep.status); //RX в VALID
|
||||||
|
ep.status = SET_STALL_TX(ep.status); //TX в STALL
|
||||||
|
}
|
||||||
|
MSG("; end\n");
|
||||||
|
return ep.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write handler
|
||||||
|
static uint16_t EP2_Handler(ep_t ep){
|
||||||
|
MSG("EP2 ");
|
||||||
|
if (ep.rx_flag){ //Пришли новые данные
|
||||||
|
MSG("read");
|
||||||
|
#ifdef EBUG
|
||||||
|
printu(ep.rx_cnt);
|
||||||
|
#endif
|
||||||
|
if(ep.rx_cnt > 2){
|
||||||
|
len = ep.rx_cnt;
|
||||||
|
rcvflag = 1;
|
||||||
|
EP_Read(2, buffer);
|
||||||
|
}
|
||||||
|
//EP_WriteIRQ(3, buffer, ep.rx_cnt);
|
||||||
|
//Так как мы ожидаем новый запрос от хоста, устанавливаем
|
||||||
|
ep.status = SET_VALID_RX(ep.status);
|
||||||
|
//ep.status = SET_STALL_TX(ep.status);
|
||||||
|
//ep.status = SET_VALID_TX(ep.status); //TX
|
||||||
|
//ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK
|
||||||
|
} else
|
||||||
|
if (ep.tx_flag){ //Данные успешно переданы
|
||||||
|
MSG("write");
|
||||||
|
ep.status = SET_VALID_RX(ep.status); //RX в VALID
|
||||||
|
ep.status = SET_STALL_TX(ep.status); //TX в STALL
|
||||||
|
}
|
||||||
|
MSG("; end\n");
|
||||||
|
return ep.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read handler
|
||||||
|
static uint16_t EP3_Handler(ep_t ep){
|
||||||
|
MSG("EP3 ");
|
||||||
|
if (ep.rx_flag){ //Пришли новые данные
|
||||||
|
MSG("read");
|
||||||
|
EP_Read(3, buffer);
|
||||||
|
ep.status = SET_VALID_TX(ep.status); //TX
|
||||||
|
ep.status = KEEP_STAT_RX(ep.status); //RX оставляем в NAK
|
||||||
|
} else
|
||||||
|
if (ep.tx_flag){ //Данные успешно переданы
|
||||||
|
MSG("write");
|
||||||
|
ep.status = SET_VALID_RX(ep.status); //RX в VALID
|
||||||
|
ep.status = SET_STALL_TX(ep.status); //TX в STALL
|
||||||
|
}
|
||||||
|
MSG("; end\n");
|
||||||
|
return ep.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USB_setup(){
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB
|
||||||
|
RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB
|
||||||
|
RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48
|
||||||
|
while(!(RCC->CR2 & RCC_CR2_HSI48RDY));
|
||||||
|
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
|
||||||
|
CRS->CFGR &= ~CRS_CFGR_SYNCSRC;
|
||||||
|
CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source
|
||||||
|
CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim
|
||||||
|
CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only
|
||||||
|
RCC->CFGR |= RCC_CFGR_SW;
|
||||||
|
//Разрешаем прерывания по RESET и CTRM
|
||||||
|
USB -> CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
|
||||||
|
//Сбрасываем флаги
|
||||||
|
USB -> ISTR = 0;
|
||||||
|
//Включаем подтяжку на D+
|
||||||
|
USB -> BCDR |= USB_BCDR_DPPU;
|
||||||
|
NVIC_EnableIRQ(USB_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_proc(){
|
||||||
|
static int8_t usbON = 0;
|
||||||
|
if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints
|
||||||
|
if(!usbON){ // endpoints not activated
|
||||||
|
MSG("Configured; activate other endpoints\n");
|
||||||
|
// make new BULK endpoint
|
||||||
|
// Buffer have 1024 bytes, but last 256 we use for CAN bus
|
||||||
|
// first free is 64; 768 - CAN data
|
||||||
|
// free: 64 128 192 256 320 384 448 512 576 640 704
|
||||||
|
// (first 192 free bytes are for EP0)
|
||||||
|
EP_Init(1, EP_TYPE_INTERRUPT, 256, 320, EP1_Handler);
|
||||||
|
EP_Init(2, EP_TYPE_BULK, 384, 448, EP2_Handler);
|
||||||
|
EP_Init(3, EP_TYPE_BULK, 512, 576, EP3_Handler);
|
||||||
|
usbON = 1;
|
||||||
|
}else{
|
||||||
|
if(rcvflag){
|
||||||
|
EP_Write(3, buffer, len);
|
||||||
|
MSG("read: ");
|
||||||
|
if(len > 2) while(LINE_BUSY == usart_send((char*)&buffer[2], len-2));
|
||||||
|
rcvflag = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
usbON = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
F0-nolib/usbcdc/usb.h
Normal file
32
F0-nolib/usbcdc/usb.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* usb.h
|
||||||
|
*
|
||||||
|
* Copyright 2018 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 __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
|
#include "hardware.h"
|
||||||
|
|
||||||
|
void USB_setup();
|
||||||
|
void usb_proc();
|
||||||
|
|
||||||
|
#endif // __USB_H__
|
||||||
69
F0-nolib/usbcdc/usb_defs.h
Normal file
69
F0-nolib/usbcdc/usb_defs.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef __USB_DEFS_H__
|
||||||
|
#define __USB_DEFS_H__
|
||||||
|
|
||||||
|
#include <stm32f0xx.h>
|
||||||
|
|
||||||
|
#define USB_BTABLE_BASE 0x40006000
|
||||||
|
#undef USB_BTABLE
|
||||||
|
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
|
||||||
|
#define USB_ISTR_EPID 0x0000000F
|
||||||
|
#define USB_FNR_LSOF_0 0x00000800
|
||||||
|
#define USB_FNR_lSOF_1 0x00001000
|
||||||
|
#define USB_LPMCSR_BESL_0 0x00000010
|
||||||
|
#define USB_LPMCSR_BESL_1 0x00000020
|
||||||
|
#define USB_LPMCSR_BESL_2 0x00000040
|
||||||
|
#define USB_LPMCSR_BESL_3 0x00000080
|
||||||
|
#define USB_EPnR_CTR_RX 0x00008000
|
||||||
|
#define USB_EPnR_DTOG_RX 0x00004000
|
||||||
|
#define USB_EPnR_STAT_RX 0x00003000
|
||||||
|
#define USB_EPnR_STAT_RX_0 0x00001000
|
||||||
|
#define USB_EPnR_STAT_RX_1 0x00002000
|
||||||
|
#define USB_EPnR_SETUP 0x00000800
|
||||||
|
#define USB_EPnR_EP_TYPE 0x00000600
|
||||||
|
#define USB_EPnR_EP_TYPE_0 0x00000200
|
||||||
|
#define USB_EPnR_EP_TYPE_1 0x00000400
|
||||||
|
#define USB_EPnR_EP_KIND 0x00000100
|
||||||
|
#define USB_EPnR_CTR_TX 0x00000080
|
||||||
|
#define USB_EPnR_DTOG_TX 0x00000040
|
||||||
|
#define USB_EPnR_STAT_TX 0x00000030
|
||||||
|
#define USB_EPnR_STAT_TX_0 0x00000010
|
||||||
|
#define USB_EPnR_STAT_TX_1 0x00000020
|
||||||
|
#define USB_EPnR_EA 0x0000000F
|
||||||
|
#define USB_COUNTn_RX_BLSIZE 0x00008000
|
||||||
|
#define USB_COUNTn_NUM_BLOCK 0x00007C00
|
||||||
|
#define USB_COUNTn_RX 0x0000003F
|
||||||
|
|
||||||
|
#define USB_TypeDef USB_TypeDef_custom
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
__IO uint32_t EPnR[8];
|
||||||
|
__IO uint32_t RESERVED1;
|
||||||
|
__IO uint32_t RESERVED2;
|
||||||
|
__IO uint32_t RESERVED3;
|
||||||
|
__IO uint32_t RESERVED4;
|
||||||
|
__IO uint32_t RESERVED5;
|
||||||
|
__IO uint32_t RESERVED6;
|
||||||
|
__IO uint32_t RESERVED7;
|
||||||
|
__IO uint32_t RESERVED8;
|
||||||
|
__IO uint32_t CNTR;
|
||||||
|
__IO uint32_t ISTR;
|
||||||
|
__IO uint32_t FNR;
|
||||||
|
__IO uint32_t DADDR;
|
||||||
|
__IO uint32_t BTABLE;
|
||||||
|
__IO uint32_t LPMCSR;
|
||||||
|
__IO uint32_t BCDR;
|
||||||
|
} USB_TypeDef;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
__IO uint16_t USB_ADDR_TX;
|
||||||
|
__IO uint16_t USB_COUNT_TX;
|
||||||
|
__IO uint16_t USB_ADDR_RX;
|
||||||
|
__IO uint16_t USB_COUNT_RX;
|
||||||
|
} USB_EPDATA_TypeDef;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
__IO USB_EPDATA_TypeDef EP[8];
|
||||||
|
} USB_BtableDef;
|
||||||
|
|
||||||
|
#endif // __USB_DEFS_H__
|
||||||
499
F0-nolib/usbcdc/usb_lib.c
Normal file
499
F0-nolib/usbcdc/usb_lib.c
Normal file
@ -0,0 +1,499 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include "usb_lib.h"
|
||||||
|
#ifdef EBUG
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
#include "usart.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEVICE_DESCRIPTOR_SIZE_BYTE (18)
|
||||||
|
#define DEVICE_QALIFIER_SIZE_BYTE (10)
|
||||||
|
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
|
||||||
|
|
||||||
|
const uint8_t USB_DeviceDescriptor[] = {
|
||||||
|
DEVICE_DESCRIPTOR_SIZE_BYTE, // bLength
|
||||||
|
0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE
|
||||||
|
0x00, // bcdUSB_L
|
||||||
|
0x02, // bcdUSB_H
|
||||||
|
0x00, // bDeviceClass - USB_COMM
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize
|
||||||
|
0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303
|
||||||
|
0x06, // idVendor_H
|
||||||
|
0x03, // idProduct_L
|
||||||
|
0x23, // idProduct_H
|
||||||
|
0x00, // bcdDevice_Ver_L
|
||||||
|
0x01, // bcdDevice_Ver_H
|
||||||
|
0x01, // iManufacturer
|
||||||
|
0x02, // iProduct
|
||||||
|
0x00, // iSerialNumber
|
||||||
|
0x01 // bNumConfigurations
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t USB_DeviceQualifierDescriptor[] = {
|
||||||
|
DEVICE_QALIFIER_SIZE_BYTE, //bLength
|
||||||
|
0x06, // bDescriptorType
|
||||||
|
0x00, // bcdUSB_L
|
||||||
|
0x02, // bcdUSB_H
|
||||||
|
0x00, // bDeviceClass
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize0
|
||||||
|
0x01, // bNumConfigurations
|
||||||
|
0x00 // Reserved
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
const uint8_t USB_ConfigDescriptor[] = {
|
||||||
|
/*Configuration Descriptor*/
|
||||||
|
0x09, /* bLength: Configuration Descriptor size */
|
||||||
|
0x02, /* bDescriptorType: Configuration */
|
||||||
|
39, /* wTotalLength:no of returned bytes */
|
||||||
|
0x00,
|
||||||
|
0x02, /* bNumInterfaces: 2 interface */
|
||||||
|
0x01, /* bConfigurationValue: Configuration value */
|
||||||
|
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||||
|
0x80, /* bmAttributes - Bus powered */
|
||||||
|
0x32, /* MaxPower 100 mA */
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*Interface Descriptor */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
0x04, /* bDescriptorType: Interface */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x01, /* bNumEndpoints: One endpoints used */
|
||||||
|
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||||
|
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||||
|
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||||
|
0x00, /* iInterface: */
|
||||||
|
|
||||||
|
/*Header Functional Descriptor*/
|
||||||
|
0x05, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||||
|
0x10, /* bcdCDC: spec release number */
|
||||||
|
0x01,
|
||||||
|
|
||||||
|
/*Call Management Functional Descriptor*/
|
||||||
|
0x05, /* bFunctionLength */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||||
|
0x00, /* bmCapabilities: D0+D1 */
|
||||||
|
0x01, /* bDataInterface: 1 */
|
||||||
|
|
||||||
|
/*ACM Functional Descriptor*/
|
||||||
|
0x04, /* bFunctionLength */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||||
|
0x02, /* bmCapabilities */
|
||||||
|
|
||||||
|
/*Union Functional Descriptor*/
|
||||||
|
0x05, /* bFunctionLength */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x06, /* bDescriptorSubtype: Union func desc */
|
||||||
|
0x00, /* bMasterInterface: Communication class interface */
|
||||||
|
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||||
|
|
||||||
|
/*Endpoint 2 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x81, /* bEndpointAddress IN1 */
|
||||||
|
0x03, /* bmAttributes: Interrupt */
|
||||||
|
0x08, /* wMaxPacketSize LO: */
|
||||||
|
0x00, /* wMaxPacketSize HI: */
|
||||||
|
0x10, /* bInterval: */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*Data class interface descriptor*/
|
||||||
|
0x09, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x04, /* bDescriptorType: */
|
||||||
|
0x01, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x02, /* bNumEndpoints: Two endpoints used */
|
||||||
|
0x0A, /* bInterfaceClass: CDC */
|
||||||
|
0x02, /* bInterfaceSubClass: */
|
||||||
|
0x00, /* bInterfaceProtocol: */
|
||||||
|
0x00, /* iInterface: */
|
||||||
|
|
||||||
|
/*Endpoint IN2 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x82, /* bEndpointAddress IN2 */
|
||||||
|
0x02, /* bmAttributes: Bulk */
|
||||||
|
64, /* wMaxPacketSize: */
|
||||||
|
0x00,
|
||||||
|
0x00, /* bInterval: ignore for Bulk transfer */
|
||||||
|
|
||||||
|
/*Endpoint OUT3 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x03, /* bEndpointAddress */
|
||||||
|
0x02, /* bmAttributes: Bulk */
|
||||||
|
64, /* wMaxPacketSize: */
|
||||||
|
0,
|
||||||
|
0x00 /* bInterval: ignore for Bulk transfer */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint8_t USB_ConfigDescriptor[] = {
|
||||||
|
/*Configuration Descriptor*/
|
||||||
|
0x09, /* bLength: Configuration Descriptor size */
|
||||||
|
0x02, /* bDescriptorType: Configuration */
|
||||||
|
53, /* wTotalLength:no of returned bytes */
|
||||||
|
0x00,
|
||||||
|
0x01, /* bNumInterfaces: 1 interface */
|
||||||
|
0x01, /* bConfigurationValue: Configuration value */
|
||||||
|
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||||
|
0x80, /* bmAttributes - Bus powered */
|
||||||
|
0x32, /* MaxPower 100 mA */
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*Interface Descriptor */
|
||||||
|
0x09, /* bLength: Interface Descriptor size */
|
||||||
|
0x04, /* bDescriptorType: Interface */
|
||||||
|
0x00, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x03, /* bNumEndpoints: 3 endpoints used */
|
||||||
|
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||||
|
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||||
|
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||||
|
0x00, /* iInterface: */
|
||||||
|
|
||||||
|
/*Header Functional Descriptor*/
|
||||||
|
0x05, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||||
|
0x10, /* bcdCDC: spec release number */
|
||||||
|
0x01,
|
||||||
|
|
||||||
|
/*Call Management Functional Descriptor*/
|
||||||
|
0x05, /* bFunctionLength */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||||
|
0x00, /* bmCapabilities: D0+D1 */
|
||||||
|
0x01, /* bDataInterface: 1 */
|
||||||
|
|
||||||
|
/*ACM Functional Descriptor*/
|
||||||
|
0x04, /* bFunctionLength */
|
||||||
|
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||||
|
0x02, /* bmCapabilities */
|
||||||
|
|
||||||
|
/*Endpoint 1 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x81, /* bEndpointAddress IN1 */
|
||||||
|
0x03, /* bmAttributes: Interrupt */
|
||||||
|
64, /* wMaxPacketSize LO: */
|
||||||
|
0x00, /* wMaxPacketSize HI: */
|
||||||
|
0x10, /* bInterval: */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*Endpoint IN3 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x83, /* bEndpointAddress IN3 */
|
||||||
|
0x02, /* bmAttributes: Bulk */
|
||||||
|
64, /* wMaxPacketSize: */
|
||||||
|
0x00,
|
||||||
|
0x00, /* bInterval: ignore for Bulk transfer */
|
||||||
|
|
||||||
|
/*Endpoint OUT2 Descriptor*/
|
||||||
|
0x07, /* bLength: Endpoint Descriptor size */
|
||||||
|
0x05, /* bDescriptorType: Endpoint */
|
||||||
|
0x02, /* bEndpointAddress */
|
||||||
|
0x02, /* bmAttributes: Bulk */
|
||||||
|
64, /* wMaxPacketSize: */
|
||||||
|
0x00,
|
||||||
|
0x00 /* bInterval: ignore for Bulk transfer */
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t USB_StringLangDescriptor[] = {
|
||||||
|
STRING_LANG_DESCRIPTOR_SIZE_BYTE, //bLength
|
||||||
|
0x03, //bDescriptorType
|
||||||
|
0x09, //wLANGID_L
|
||||||
|
0x04 //wLANGID_H
|
||||||
|
};
|
||||||
|
|
||||||
|
//~ typedef struct{
|
||||||
|
//~ uint8_t bLength;
|
||||||
|
//~ uint8_t bDescriptorType;
|
||||||
|
//~ uint16_t bString[];
|
||||||
|
//~ } StringDescriptor;
|
||||||
|
|
||||||
|
#define _USB_STRING_(name, str) \
|
||||||
|
const struct name \
|
||||||
|
{ \
|
||||||
|
uint8_t bLength; \
|
||||||
|
uint8_t bDescriptorType; \
|
||||||
|
wchar_t bString[(sizeof(str) - 2) / 2]; \
|
||||||
|
\
|
||||||
|
} \
|
||||||
|
name = {sizeof(name), 0x03, str};
|
||||||
|
|
||||||
|
_USB_STRING_(USB_StringSerialDescriptor, L"0.01")
|
||||||
|
_USB_STRING_(USB_StringManufacturingDescriptor, L"Russia, SAO RAS")
|
||||||
|
_USB_STRING_(USB_StringProdDescriptor, L"TSYS01 sensors controller")
|
||||||
|
|
||||||
|
usb_dev_t USB_Dev;
|
||||||
|
ep_t endpoints[MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
/*
|
||||||
|
bmRequestType: 76543210
|
||||||
|
7 direction: 0 - host->device, 1 - device->host
|
||||||
|
65 type: 0 - standard, 1 - class, 2 - vendor
|
||||||
|
4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Endpoint0 (control) handler
|
||||||
|
* @param ep - endpoint state
|
||||||
|
* @return data written to EP0R
|
||||||
|
*/
|
||||||
|
uint16_t Enumerate_Handler(ep_t ep){
|
||||||
|
config_pack_t *packet = (config_pack_t *)ep.rx_buf;
|
||||||
|
uint16_t status = 0; // bus powered
|
||||||
|
void wr0(const uint8_t *buf, uint16_t size){
|
||||||
|
if(packet->wLength < size) size = packet->wLength;
|
||||||
|
EP_WriteIRQ(0, buf, size);
|
||||||
|
}
|
||||||
|
if ((ep.rx_flag) && (ep.setup_flag)){
|
||||||
|
if (packet -> bmRequestType == 0x80){ // get device properties
|
||||||
|
switch(packet->bRequest){
|
||||||
|
case GET_DESCRIPTOR:
|
||||||
|
switch(packet->wValue){
|
||||||
|
case DEVICE_DESCRIPTOR:
|
||||||
|
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
|
||||||
|
break;
|
||||||
|
case CONFIGURATION_DESCRIPTOR:
|
||||||
|
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
|
||||||
|
break;
|
||||||
|
case STRING_LANG_DESCRIPTOR:
|
||||||
|
wr0(USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE);
|
||||||
|
break;
|
||||||
|
case STRING_MAN_DESCRIPTOR:
|
||||||
|
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
|
||||||
|
break;
|
||||||
|
case STRING_PROD_DESCRIPTOR:
|
||||||
|
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
|
||||||
|
break;
|
||||||
|
case STRING_SN_DESCRIPTOR:
|
||||||
|
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
|
||||||
|
break;
|
||||||
|
case DEVICE_QALIFIER_DESCRIPTOR:
|
||||||
|
wr0(USB_DeviceQualifierDescriptor, DEVICE_QALIFIER_SIZE_BYTE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MSG("val");
|
||||||
|
printuhex(packet->wValue);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GET_STATUS:
|
||||||
|
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MSG("req");
|
||||||
|
printuhex(packet->bRequest);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
//ôÁË ËÁË ÍÙ ÎÅ ÏÖÉÄÁÅÍ ÐÒÉÅÍÁ É ÚÁÎÉÍÁÅÍÓÑ ÔÏÌØËÏ ÐÅÒÅÄÁÞÅÊ, ÔÏ ÕÓÔÁÎÁ×ÌÉ×ÁÅÍ
|
||||||
|
ep.status = SET_NAK_RX(ep.status);
|
||||||
|
ep.status = SET_VALID_TX(ep.status);
|
||||||
|
}else if(packet->bmRequestType == 0x00){ // set device properties
|
||||||
|
switch(packet->bRequest){
|
||||||
|
case SET_ADDRESS:
|
||||||
|
//óÒÁÚÕ ÐÒÉÓ×ÏÉÔØ ÁÄÒÅÓ × DADDR ÎÅÌØÚÑ, ÔÁË ËÁË ÈÏÓÔ ÏÖÉÄÁÅÔ ÐÏÄÔ×ÅÒÖÄÅÎÉÑ
|
||||||
|
//ÐÒÉÅÍÁ ÓÏ ÓÔÁÒÙÍ ÁÄÒÅÓÏÍ
|
||||||
|
USB_Dev.USB_Addr = packet -> wValue;
|
||||||
|
break;
|
||||||
|
case SET_CONFIGURATION:
|
||||||
|
//õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÓÏÓÔÏÑÎÉÅ × "óËÏÎÆÉÇÕÒÉÒÏ×ÁÎÏ"
|
||||||
|
USB_Dev.USB_Status = USB_CONFIGURE_STATE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MSG("req");
|
||||||
|
printuhex(packet->bRequest);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
//ÏÔÐÒÁ×ÌÑÅÍ ÐÏÄÔ×ÅÒÖÄÅÎÉÅ ÐÒÉÅÍÁ
|
||||||
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
|
//ôÁË ËÁË ÍÙ ÎÅ ÏÖÉÄÁÅÍ ÐÒÉÅÍÁ É ÚÁÎÉÍÁÅÍÓÑ ÔÏÌØËÏ ÐÅÒÅÄÁÞÅÊ, ÔÏ ÕÓÔÁÎÁ×ÌÉ×ÁÅÍ
|
||||||
|
ep.status = SET_NAK_RX(ep.status);
|
||||||
|
ep.status = SET_VALID_TX(ep.status);
|
||||||
|
}else if(packet -> bmRequestType == 0x02){
|
||||||
|
if (packet->bRequest == CLEAR_FEATURE){
|
||||||
|
//ÏÔÐÒÁ×ÌÑÅÍ ÐÏÄÔ×ÅÒÖÄÅÎÉÅ ÐÒÉÅÍÁ
|
||||||
|
EP_WriteIRQ(0, (uint8_t *)0, 0);
|
||||||
|
//ôÁË ËÁË ÍÙ ÎÅ ÏÖÉÄÁÅÍ ÐÒÉÅÍÁ É ÚÁÎÉÍÁÅÍÓÑ ÔÏÌØËÏ ÐÅÒÅÄÁÞÅÊ, ÔÏ ÕÓÔÁÎÁ×ÌÉ×ÁÅÍ
|
||||||
|
ep.status = SET_NAK_RX(ep.status);
|
||||||
|
ep.status = SET_VALID_TX(ep.status);
|
||||||
|
}else{
|
||||||
|
MSG("req");
|
||||||
|
printuhex(packet->bRequest);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (ep.rx_flag){ //ðÏÄÔ×ÅÒÖÅÎÉÅ ÐÒÉÅÍÁ ÈÏÓÔÏÍ
|
||||||
|
//ôÁË ËÁË ÐÏÔ×ÅÒÖÄÅÎÉÅ ÏÔ ÈÏÓÔÁ ÚÁ×ÅÒÛÁÅÔ ÔÒÁÎÚÁËÃÉÀ
|
||||||
|
//ÔÏ ÓÂÒÁÓÙ×ÁÅÍ DTOGÉ
|
||||||
|
ep.status = CLEAR_DTOG_RX(ep.status);
|
||||||
|
ep.status = CLEAR_DTOG_TX(ep.status);
|
||||||
|
//ôÁË ËÁË ÍÙ ÏÖÉÄÁÅÍ ÎÏ×ÙÊ ÚÁÐÒÏÓ ÏÔ ÈÏÓÔÁ, ÕÓÔÁÎÁ×ÌÉ×ÁÅÍ
|
||||||
|
ep.status = SET_VALID_RX(ep.status);
|
||||||
|
ep.status = SET_STALL_TX(ep.status);
|
||||||
|
} else
|
||||||
|
if (ep.tx_flag){ //õÓÐÅÛÎÁÑ ÐÅÒÅÄÁÞÁ ÐÁËÅÔÁ
|
||||||
|
//åÓÌÉ ÐÏÌÕÞÅÎÎÙÊ ÏÔ ÈÏÓÔÁ ÁÄÒÅÓ ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ÁÄÒÅÓÏÍ ÕÓÔÒÏÊÓÔ×Á
|
||||||
|
if ((USB -> DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
|
||||||
|
//ðÒÉÓ×ÁÉ×ÁÅÍ ÎÏ×ÙÊ ÁÄÒÅÓ ÕÓÔÒÏÊÓÔ×Õ
|
||||||
|
USB -> DADDR = USB_DADDR_EF | USB_Dev.USB_Addr;
|
||||||
|
//õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÓÏÓÔÏÑÎÉÅ × "áÄÒÅÓÏ×ÁÎÎÏ"
|
||||||
|
USB_Dev.USB_Status = USB_ADRESSED_STATE;
|
||||||
|
}
|
||||||
|
//ëÏÎÅà ÔÒÁÎÚÁËÃÉÉ, ÏÞÉÝÁÅÍ DTOG
|
||||||
|
ep.status = CLEAR_DTOG_RX(ep.status);
|
||||||
|
ep.status = CLEAR_DTOG_TX(ep.status);
|
||||||
|
//ïÖÉÄÁÅÍ ÎÏ×ÙÊ ÚÁÐÒÏÓ, ÉÌÉ ÐÏ×ÔÏÒÎÏÅ ÞÔÅÎÉÅ ÄÁÎÎÙÈ (ÏÛÉÂËÁ ÐÒÉ ÐÅÒÅÄÁÞÅ)
|
||||||
|
//ÐÏÜÔÏÍÕ Rx É Tx × VALID
|
||||||
|
ep.status = SET_VALID_RX(ep.status);
|
||||||
|
ep.status = SET_VALID_TX(ep.status);
|
||||||
|
}
|
||||||
|
//ÚÎÁÞÅÎÉÅ ep.status ÂÕÄÅÔ ÚÁÐÉÓÁÎÏ × EPnR É ÓÏÏÔ×ÅÔ×Ó×ÅÎÎÏ ÓÂÒÏÛÅÎÙ ÉÌÉ ÕÓÔÁÎÏ×ÌÅÎÙ
|
||||||
|
//ÓÏÏÔ×ÅÔÓ×ÕÀÝÉÅ ÂÉÔÙ
|
||||||
|
return ep.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* éÎÉÃÉÁÌÉÚÁÃÉÑ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
* number - ÎÏÍÅÒ (0...7)
|
||||||
|
* type - ÔÉÐ ËÏÎÅÞÎÏÊ ÔÏÞËÉ (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT)
|
||||||
|
* addr_tx - ÁÄÒÅÓ ÐÅÒÅÄÁÀÝÅÇÏ ÂÕÆÅÒÁ × ÐÅÒÉÆÅÒÉÉ USB
|
||||||
|
* addr_rx - ÁÄÒÅÓ ÐÒÉÅÍÎÏÇÏ ÂÕÆÅÒÁ × ÐÅÒÉÆÅÒÉÉ USB
|
||||||
|
* òÁÚÍÅÒ ÐÒÉÅÍÎÏÇÏ ÂÕÆÅÒÁ - ÆÉËÓÉÒÏ×ÁÎÎÙÊ 64 ÂÁÊÔÁ
|
||||||
|
* uint16_t (*func)(ep_t *ep) - ÁÄÒÅÓ ÆÕÎËÃÉÉ ÏÂÒÁÂÏÔÞÉËÁ ÓÏÂÙÔÉÊ ËÏÎÔÒÏÌØÎÏÊ ÔÏÞËÉ (ÐÒÅÒÙ×ÁÎÉÑ)
|
||||||
|
*/
|
||||||
|
void EP_Init(uint8_t number, uint8_t type, uint16_t addr_tx, uint16_t addr_rx, uint16_t (*func)(ep_t ep)){
|
||||||
|
USB -> EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
|
||||||
|
USB -> EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
|
||||||
|
USB_BTABLE -> EP[number].USB_ADDR_TX = addr_tx;
|
||||||
|
USB_BTABLE -> EP[number].USB_COUNT_TX = 0;
|
||||||
|
USB_BTABLE -> EP[number].USB_ADDR_RX = addr_rx;
|
||||||
|
USB_BTABLE -> EP[number].USB_COUNT_RX = 0x8400; // buffer size (64 bytes): Table127 of RM: BL_SIZE=1, NUM_BLOCK=1
|
||||||
|
endpoints[number].func = func;
|
||||||
|
endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + addr_tx);
|
||||||
|
endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + addr_rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ïÂÒÁÂÏÔÞÉË ÐÒÅÒÙ×ÁÎÉÊ USB
|
||||||
|
void usb_isr(){
|
||||||
|
uint8_t n;
|
||||||
|
if (USB -> ISTR & USB_ISTR_RESET){
|
||||||
|
// Reinit registers
|
||||||
|
USB -> CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM;
|
||||||
|
USB -> ISTR = 0;
|
||||||
|
// Endpoint 0 - CONTROL (128 bytes for TX and 64 for RX)
|
||||||
|
EP_Init(0, EP_TYPE_CONTROL, 64, 192, Enumerate_Handler);
|
||||||
|
//ïÂÎÕÌÑÅÍ ÁÄÒÅÓ ÕÓÔÒÏÊÓÔ×Á
|
||||||
|
USB -> DADDR = USB_DADDR_EF;
|
||||||
|
//ðÒÉÓ×ÁÉ×ÁÅÍ ÓÏÓÔÏÑÎÉÅ × DEFAULT (ÏÖÉÄÁÎÉÅ ÜÎÕÍÅÒÁÃÉÉ)
|
||||||
|
USB_Dev.USB_Status = USB_DEFAULT_STATE;
|
||||||
|
}
|
||||||
|
if (USB -> ISTR & USB_ISTR_CTR){
|
||||||
|
//ïÐÒÅÄÅÌÑÅÍ ÎÏÍÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ, ×ÙÚ×Á×ÛÅÊ ÐÒÅÒÙ×ÁÎÉÅ
|
||||||
|
n = USB -> ISTR & USB_ISTR_EPID;
|
||||||
|
//ëÏÐÉÒÕÅÍ ËÏÌÉÞÅÓÔ×Ï ÐÒÉÎÑÔÙÈ ÂÁÊÔ
|
||||||
|
endpoints[n].rx_cnt = USB_BTABLE -> EP[n].USB_COUNT_RX;
|
||||||
|
//ëÏÐÉÒÕÅÍ ÓÏÄÅÒÖÉÍÏÅ EPnR ÜÔÏÊ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
endpoints[n].status = USB -> EPnR[n];
|
||||||
|
//óÂÒÁÓÙ×ÁÅÍ ÆÌÁÖËÉ
|
||||||
|
endpoints[n].rx_flag = 0;
|
||||||
|
endpoints[n].tx_flag = 0;
|
||||||
|
endpoints[n].setup_flag = 0;
|
||||||
|
//õÓÔÁÎÁ×ÌÉ×ÁÅÍ ÎÕÖÎÙÅ ÆÌÁÖËÉ
|
||||||
|
if (endpoints[n].status & USB_EPnR_CTR_RX) endpoints[n].rx_flag = 1;
|
||||||
|
if (endpoints[n].status & USB_EPnR_SETUP) endpoints[n].setup_flag = 1;
|
||||||
|
if (endpoints[n].status & USB_EPnR_CTR_TX) endpoints[n].tx_flag = 1;
|
||||||
|
//÷ÙÚÙ×ÁÅÍ ÆÕÎËÃÉÀ-ÏÂÒÁÂÏÔÞÉË ÓÏÂÙÔÉÑ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
//Ó ÐÏÓÌÅÄÕÀÝÅÊ ÚÁÐÉÓØÀ × ÒÅÇÉÓÔÒ EPnR ÒÅÚÕÌØÔÁÔÁ
|
||||||
|
endpoints[n].status = endpoints[n].func(endpoints[n]);
|
||||||
|
//îÅ ÍÅÎÑÅÍ ÓÏÓÔÏÑÎÉÅ DTOG
|
||||||
|
endpoints[n].status = KEEP_DTOG_TX(endpoints[n].status);
|
||||||
|
endpoints[n].status = KEEP_DTOG_RX(endpoints[n].status);
|
||||||
|
//ïÞÉÝÁÅÍ ÆÌÁÇÉ ÐÒÉÅÍÁ É ÐÅÒÅÄÁÞÉ
|
||||||
|
endpoints[n].status = CLEAR_CTR_RX(endpoints[n].status);
|
||||||
|
endpoints[n].status = CLEAR_CTR_TX(endpoints[n].status);
|
||||||
|
USB -> EPnR[n] = endpoints[n].status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* æÕÎËÃÉÑ ÚÁÐÉÓÉ ÍÁÓÓÉ×Á × ÂÕÆÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ (÷ùúï÷ éú ðòåòù÷áîéñ)
|
||||||
|
* number - ÎÏÍÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
* *buf - ÁÄÒÅÓ ÍÁÓÓÉ×Á Ó ÚÁÐÉÓÙ×ÁÅÍÙÍÉ ÄÁÎÎÙÍÉ
|
||||||
|
* size - ÒÁÚÍÅÒ ÍÁÓÓÉ×Á
|
||||||
|
*/
|
||||||
|
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
|
||||||
|
uint8_t i;
|
||||||
|
/*
|
||||||
|
* ÷îéíáîéå ëïóôùìø
|
||||||
|
* éÚ-ÚÁ ÏÛÉÂËÉ ÚÁÐÉÓÉ × ÏÂÌÁÓÔØ USB/CAN SRAM Ó 8-ÂÉÔÎÙÍ ÄÏÓÔÕÐÏÍ
|
||||||
|
* ÐÒÉÛÌÏÓØ ÕÐÁËÏ×Ù×ÁÔØ ÍÁÓÓÉ× × 16-ÂÉÔ, ÓÏÏÂ×ÅÔÓÔ×ÅÎÎÏ ÒÁÚÍÅÒ ÄÅÌÉÔØ
|
||||||
|
* ÎÁ 2, ÅÓÌÉ ÏÎ ÂÙÌ ÞÅÔÎÙÊ, ÉÌÉ ÄÅÌÉÔØ ÎÁ 2 + 1 ÅÓÌÉ ÎÅÞÅÔÎÙÊ
|
||||||
|
*/
|
||||||
|
uint16_t temp = (size & 0x0001) ? (size + 1) / 2 : size / 2;
|
||||||
|
uint16_t *buf16 = (uint16_t *)buf;
|
||||||
|
for (i = 0; i < temp; i++){
|
||||||
|
endpoints[number].tx_buf[i] = buf16[i];
|
||||||
|
}
|
||||||
|
//ëÏÌÉÞÅÓÔ×Ï ÐÅÒÅÄÁ×ÁÅÍÙÈ ÂÁÊÔ
|
||||||
|
USB_BTABLE -> EP[number].USB_COUNT_TX = size;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* æÕÎËÃÉÑ ÚÁÐÉÓÉ ÍÁÓÓÉ×Á × ÂÕÆÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ (÷ùúï÷ éú÷îå ðòåòù÷áîéñ)
|
||||||
|
* number - ÎÏÍÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
* *buf - ÁÄÒÅÓ ÍÁÓÓÉ×Á Ó ÚÁÐÉÓÙ×ÁÅÍÙÍÉ ÄÁÎÎÙÍÉ
|
||||||
|
* size - ÒÁÚÍÅÒ ÍÁÓÓÉ×Á
|
||||||
|
*/
|
||||||
|
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
|
||||||
|
uint8_t i;
|
||||||
|
uint16_t status = USB -> EPnR[number];
|
||||||
|
/*
|
||||||
|
* ÷îéíáîéå ëïóôùìø
|
||||||
|
* éÚ-ÚÁ ÏÛÉÂËÉ ÚÁÐÉÓÉ × ÏÂÌÁÓÔØ USB/CAN SRAM Ó 8-ÂÉÔÎÙÍ ÄÏÓÔÕÐÏÍ
|
||||||
|
* ÐÒÉÛÌÏÓØ ÕÐÁËÏ×Ù×ÁÔØ ÍÁÓÓÉ× × 16-ÂÉÔ, ÓÏÏÂ×ÅÔÓÔ×ÅÎÎÏ ÒÁÚÍÅÒ ÄÅÌÉÔØ
|
||||||
|
* ÎÁ 2, ÅÓÌÉ ÏÎ ÂÙÌ ÞÅÔÎÙÊ, ÉÌÉ ÄÅÌÉÔØ ÎÁ 2 + 1 ÅÓÌÉ ÎÅÞÅÔÎÙÊ
|
||||||
|
*/
|
||||||
|
uint16_t temp = (size & 0x0001) ? (size + 1) / 2 : size / 2;
|
||||||
|
uint16_t *buf16 = (uint16_t *)buf;
|
||||||
|
for (i = 0; i < temp; i++){
|
||||||
|
endpoints[number].tx_buf[i] = buf16[i];
|
||||||
|
}
|
||||||
|
//ëÏÌÉÞÅÓÔ×Ï ÐÅÒÅÄÁ×ÁÅÍÙÈ ÂÁÊÔ
|
||||||
|
USB_BTABLE -> EP[number].USB_COUNT_TX = size;
|
||||||
|
|
||||||
|
status = SET_NAK_RX(status); //RX × NAK
|
||||||
|
status = SET_VALID_TX(status); //TX × VALID
|
||||||
|
status = KEEP_DTOG_TX(status);
|
||||||
|
status = KEEP_DTOG_RX(status);
|
||||||
|
USB -> EPnR[number] = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* æÕÎËÃÉÑ ÞÔÅÎÉÑ ÍÁÓÓÉ×Á ÉÚ ÂÕÆÅÒÁ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
* number - ÎÏÍÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
* *buf - ÁÄÒÅÓ ÍÁÓÓÉ×Á ËÕÄÁ ÓÞÉÔÙ×ÁÅÍ ÄÁÎÎÙÅ
|
||||||
|
*/
|
||||||
|
void EP_Read(uint8_t number, uint8_t *buf){
|
||||||
|
uint16_t i;
|
||||||
|
for (i = 0; i < endpoints[number].rx_cnt; i++){
|
||||||
|
buf[i] = endpoints[number].rx_buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//æÕÎËÃÉÑ ÐÏÌÕÞÅÎÉÑ ÓÏÓÔÏÑÎÉÑ ÓÏÅÄÉÎÅÎÉÑ USB
|
||||||
|
uint8_t USB_GetState(){
|
||||||
|
return USB_Dev.USB_Status;
|
||||||
|
}
|
||||||
130
F0-nolib/usbcdc/usb_lib.h
Normal file
130
F0-nolib/usbcdc/usb_lib.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef __USB_LIB_H__
|
||||||
|
#define __USB_LIB_H__
|
||||||
|
|
||||||
|
#include "usb_defs.h"
|
||||||
|
|
||||||
|
//íÁËÓÉÍÁÌØÎÏÅ ËÏÌÉÞÅÓ×Ï ËÏÎÅÞÎÙÈ ÔÏÞÅË
|
||||||
|
#define MAX_ENDPOINTS 2
|
||||||
|
// bRequest, standard; for bmRequestType == 0x80
|
||||||
|
#define GET_STATUS 0x00
|
||||||
|
#define GET_DESCRIPTOR 0x06
|
||||||
|
#define GET_CONFIGURATION 0x08 //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
// for bmRequestType == 0
|
||||||
|
#define CLEAR_FEATURE 0x01
|
||||||
|
#define SET_FEATURE 0x03 //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
#define SET_ADDRESS 0x05
|
||||||
|
#define SET_DESCRIPTOR 0x07 //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
#define SET_CONFIGURATION 0x09
|
||||||
|
// for bmRequestType == 0x81, 1 or 0xB2
|
||||||
|
#define GET_INTERFACE 0x0A //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
#define SET_INTERFACE 0x0B //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
#define SYNC_FRAME 0x0C //ÎÅ ÒÅÁÌÉÚÏ×ÁÎ
|
||||||
|
|
||||||
|
// Class-Specific Control Requests
|
||||||
|
#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
|
||||||
|
|
||||||
|
/* Line Coding Structure from CDC spec 6.2.13
|
||||||
|
struct usb_cdc_line_coding {
|
||||||
|
__le32 dwDTERate;
|
||||||
|
__u8 bCharFormat;
|
||||||
|
#define USB_CDC_1_STOP_BITS 0
|
||||||
|
#define USB_CDC_1_5_STOP_BITS 1
|
||||||
|
#define USB_CDC_2_STOP_BITS 2
|
||||||
|
|
||||||
|
__u8 bParityType;
|
||||||
|
#define USB_CDC_NO_PARITY 0
|
||||||
|
#define USB_CDC_ODD_PARITY 1
|
||||||
|
#define USB_CDC_EVEN_PARITY 2
|
||||||
|
#define USB_CDC_MARK_PARITY 3
|
||||||
|
#define USB_CDC_SPACE_PARITY 4
|
||||||
|
|
||||||
|
__u8 bDataBits;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
*/
|
||||||
|
|
||||||
|
// wValue
|
||||||
|
#define DEVICE_DESCRIPTOR 0x100
|
||||||
|
#define CONFIGURATION_DESCRIPTOR 0x200
|
||||||
|
#define STRING_LANG_DESCRIPTOR 0x300
|
||||||
|
#define STRING_MAN_DESCRIPTOR 0x301
|
||||||
|
#define STRING_PROD_DESCRIPTOR 0x302
|
||||||
|
#define STRING_SN_DESCRIPTOR 0x303
|
||||||
|
#define DEVICE_QALIFIER_DESCRIPTOR 0x600
|
||||||
|
//íÁËÒÏÓÙ ÕÓÔÁÎÏ×ËÉ/ÏÞÉÓÔËÉ ÂÉÔÏ× × EPnR ÒÅÇÉÓÔÒÁÈ
|
||||||
|
#define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX))
|
||||||
|
#define SET_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? (R & (~USB_EPnR_DTOG_RX)) : R
|
||||||
|
#define TOGGLE_DTOG_RX(R) (R | USB_EPnR_DTOG_RX)
|
||||||
|
#define KEEP_DTOG_RX(R) (R & (~USB_EPnR_DTOG_RX))
|
||||||
|
#define CLEAR_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? R : (R & (~USB_EPnR_DTOG_TX))
|
||||||
|
#define SET_DTOG_TX(R) (R & USB_EPnR_DTOG_TX) ? (R & (~USB_EPnR_DTOG_TX)) : R
|
||||||
|
#define TOGGLE_DTOG_TX(R) (R | USB_EPnR_DTOG_TX)
|
||||||
|
#define KEEP_DTOG_TX(R) (R & (~USB_EPnR_DTOG_TX))
|
||||||
|
#define SET_VALID_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX) | (R & (~USB_EPnR_STAT_RX))
|
||||||
|
#define SET_NAK_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_1) | (R & (~USB_EPnR_STAT_RX))
|
||||||
|
#define SET_STALL_RX(R) ((R & USB_EPnR_STAT_RX) ^ USB_EPnR_STAT_RX_0) | (R & (~USB_EPnR_STAT_RX))
|
||||||
|
#define KEEP_STAT_RX(R) (R & (~USB_EPnR_STAT_RX))
|
||||||
|
#define SET_VALID_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX) | (R & (~USB_EPnR_STAT_TX))
|
||||||
|
#define SET_NAK_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_1) | (R & (~USB_EPnR_STAT_TX))
|
||||||
|
#define SET_STALL_TX(R) ((R & USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_TX_0) | (R & (~USB_EPnR_STAT_TX))
|
||||||
|
#define KEEP_STAT_TX(R) (R & (~USB_EPnR_STAT_TX))
|
||||||
|
#define CLEAR_CTR_RX(R) (R & (~USB_EPnR_CTR_RX))
|
||||||
|
#define CLEAR_CTR_TX(R) (R & (~USB_EPnR_CTR_TX))
|
||||||
|
#define CLEAR_CTR_RX_TX(R) (R & (~(USB_EPnR_CTR_TX | USB_EPnR_CTR_RX)))
|
||||||
|
//óÏÓÔÏÑÎÉÑ ÓÏÅÄÉÎÅÎÉÑ USB
|
||||||
|
#define USB_DEFAULT_STATE 0
|
||||||
|
#define USB_ADRESSED_STATE 1
|
||||||
|
#define USB_CONFIGURE_STATE 2
|
||||||
|
//ôÉÐÙ ËÏÎÅÞÎÙÈ ÔÏÞÅË
|
||||||
|
#define EP_TYPE_BULK 0x00
|
||||||
|
#define EP_TYPE_CONTROL 0x01
|
||||||
|
#define EP_TYPE_ISO 0x02
|
||||||
|
#define EP_TYPE_INTERRUPT 0x03
|
||||||
|
|
||||||
|
//ôÉÐ ÄÌÑ ÒÁÓÛÉÆÒÏ×ËÉ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÐÁËÅÔÁ
|
||||||
|
typedef struct {
|
||||||
|
uint8_t bmRequestType;
|
||||||
|
uint8_t bRequest;
|
||||||
|
uint16_t wValue;
|
||||||
|
uint16_t wIndex;
|
||||||
|
uint16_t wLength;
|
||||||
|
} config_pack_t;
|
||||||
|
//óÔÒÕËÔÕÒÁ ÓÏÓÔÏÑÎÉÊ ËÏÎÅÞÎÙÈ ÔÏÞÅË
|
||||||
|
typedef struct __ep_t{
|
||||||
|
uint16_t *tx_buf;
|
||||||
|
uint8_t *rx_buf;
|
||||||
|
uint16_t (*func)();
|
||||||
|
uint16_t status;
|
||||||
|
unsigned rx_cnt : 10;
|
||||||
|
unsigned tx_flag : 1;
|
||||||
|
unsigned rx_flag : 1;
|
||||||
|
unsigned setup_flag : 1;
|
||||||
|
} ep_t;
|
||||||
|
//óÔÁÔÕÓ É ÁÄÒÅÓ ÓÏÅÄÉÎÅÎÉÑ USB
|
||||||
|
typedef struct {
|
||||||
|
uint8_t USB_Status;
|
||||||
|
uint16_t USB_Addr;
|
||||||
|
} usb_dev_t;
|
||||||
|
|
||||||
|
//éÎÉÃÉÁÌÉÚÁÃÉÑ USB
|
||||||
|
void USB_Init();
|
||||||
|
//ðÏÌÕÞÉÔØ ÓÔÁÔÕÓ ÓÏÅÄÉÎÅÎÉÑ USB
|
||||||
|
uint8_t USB_GetState();
|
||||||
|
//éÎÉÃÉÁÌÉÚÁÃÉÑ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
void EP_Init(uint8_t number, uint8_t type, uint16_t addr_tx, uint16_t addr_rx, uint16_t (*func)(ep_t ep));
|
||||||
|
//úÁÐÉÓØ ÍÁÓÓÉ×Á × ÂÕÆÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ ÉÚ ÐÒÅÒÙ×ÁÎÉÑ
|
||||||
|
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
|
||||||
|
//úÁÐÉÓØ ÍÁÓÓÉ×Á × ÂÕÆÅÒ ËÏÎÅÞÎÏÊ ÔÏÞËÉ ÉÚ×ÎÅ ÐÒÅÒÙ×ÁÎÉÑ
|
||||||
|
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
|
||||||
|
//þÔÅÎÉÅ ÍÁÓÓÉ×Á ÉÚ ÂÕÆÅÒÁ ËÏÎÅÞÎÏÊ ÔÏÞËÉ
|
||||||
|
void EP_Read(uint8_t number, uint8_t *buf);
|
||||||
|
|
||||||
|
#endif // __USB_LIB_H__
|
||||||
BIN
F0-nolib/usbcdc/usbcan.bin
Executable file
BIN
F0-nolib/usbcdc/usbcan.bin
Executable file
Binary file not shown.
133
F1/2.8TFT/Makefile
Normal file
133
F1/2.8TFT/Makefile
Normal 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)
|
||||||
5
F1/2.8TFT/README
Normal file
5
F1/2.8TFT/README
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Template of USB-CDC
|
||||||
|
|
||||||
|
written for chinese devboard based on STM32F103R8T6
|
||||||
|
|
||||||
|
Press H for help
|
||||||
310
F1/2.8TFT/cdcacm.c
Normal file
310
F1/2.8TFT/cdcacm.c
Normal 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);
|
||||||
|
}
|
||||||
54
F1/2.8TFT/cdcacm.h
Normal file
54
F1/2.8TFT/cdcacm.h
Normal 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__
|
||||||
BIN
F1/2.8TFT/dma_gpio.bin
Executable file
BIN
F1/2.8TFT/dma_gpio.bin
Executable file
Binary file not shown.
74
F1/2.8TFT/dmagpio.c
Normal file
74
F1/2.8TFT/dmagpio.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
F1/2.8TFT/dmagpio.h
Normal file
32
F1/2.8TFT/dmagpio.h
Normal 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__
|
||||||
72
F1/2.8TFT/hardware_ini.c
Normal file
72
F1/2.8TFT/hardware_ini.c
Normal 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();
|
||||||
|
}
|
||||||
95
F1/2.8TFT/hardware_ini.h
Normal file
95
F1/2.8TFT/hardware_ini.h
Normal 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
F1/2.8TFT/lcd.c
Normal file
433
F1/2.8TFT/lcd.c
Normal 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);
|
||||||
|
}
|
||||||
68
F1/2.8TFT/lcd.h
Normal file
68
F1/2.8TFT/lcd.h
Normal 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__
|
||||||
9
F1/2.8TFT/ld/devices.data
Normal file
9
F1/2.8TFT/ld/devices.data
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
stm32f103?4* stm32f1 ROM=16K RAM=6K
|
||||||
|
stm32f103?6* stm32f1 ROM=32K RAM=10K
|
||||||
|
stm32f103?8* stm32f1 ROM=64K RAM=20K
|
||||||
|
stm32f103?b* stm32f1 ROM=128K RAM=20K
|
||||||
|
stm32f103?c* stm32f1 ROM=256K RAM=48K
|
||||||
|
stm32f103?d* stm32f1 ROM=384K RAM=64K
|
||||||
|
stm32f103?e* stm32f1 ROM=512K RAM=64K
|
||||||
|
stm32f103?f* stm32f1 ROM=768K RAM=96K
|
||||||
|
stm32f103?g* stm32f1 ROM=1024K RAM=96K
|
||||||
31
F1/2.8TFT/ld/stm32f103x4.ld
Normal file
31
F1/2.8TFT/ld/stm32f103x4.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 6K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103x6.ld
Normal file
31
F1/2.8TFT/ld/stm32f103x6.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103x8.ld
Normal file
31
F1/2.8TFT/ld/stm32f103x8.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xB.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xB.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xC.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xC.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xD.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xD.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 384K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xE.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xE.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xF.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xF.ld
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Linker script for STM32F100x4, 16K flash, 4K RAM. */
|
||||||
|
|
||||||
|
/* Define memory regions. */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 768K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the common ld script. */
|
||||||
|
INCLUDE libopencm3_stm32f1.ld
|
||||||
|
|
||||||
31
F1/2.8TFT/ld/stm32f103xG.ld
Normal file
31
F1/2.8TFT/ld/stm32f103xG.ld
Normal 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
F1/2.8TFT/main.c
Normal file
128
F1/2.8TFT/main.c
Normal 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);
|
||||||
|
}
|
||||||
53
F1/2.8TFT/main.h
Normal file
53
F1/2.8TFT/main.h
Normal 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__
|
||||||
|
|
||||||
172
F1/2.8TFT/registers.h
Normal file
172
F1/2.8TFT/registers.h
Normal 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
|
||||||
93
F1/2.8TFT/sync.c
Normal file
93
F1/2.8TFT/sync.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the libopencm3 project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
* implement mutexes for other type of MCU (which doesn't have strex & ldrex)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libopencm3/cm3/sync.h>
|
||||||
|
|
||||||
|
/* DMB is supported on CM0 */
|
||||||
|
void __dmb()
|
||||||
|
{
|
||||||
|
__asm__ volatile ("dmb");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Those are defined only on CM3 or CM4 */
|
||||||
|
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||||
|
|
||||||
|
uint32_t __ldrex(volatile uint32_t *addr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t __strex(uint32_t val, volatile uint32_t *addr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm__ volatile ("strex %0, %2, [%1]"
|
||||||
|
: "=&r" (res) : "r" (addr), "r" (val));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_lock(mutex_t *m)
|
||||||
|
{
|
||||||
|
uint32_t status = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Wait until the mutex is unlocked. */
|
||||||
|
while (__ldrex(m) != MUTEX_UNLOCKED);
|
||||||
|
|
||||||
|
/* Try to acquire it. */
|
||||||
|
status = __strex(MUTEX_LOCKED, m);
|
||||||
|
|
||||||
|
/* Did we get it? If not then try again. */
|
||||||
|
} while (status != 0);
|
||||||
|
|
||||||
|
/* Execute the mysterious Data Memory Barrier instruction! */
|
||||||
|
__dmb();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_unlock(mutex_t *m)
|
||||||
|
{
|
||||||
|
/* Ensure accesses to protected resource are finished */
|
||||||
|
__dmb();
|
||||||
|
|
||||||
|
/* Free the lock. */
|
||||||
|
*m = MUTEX_UNLOCKED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to lock mutex
|
||||||
|
* if it's already locked or there was error in STREX, return MUTEX_LOCKED
|
||||||
|
* else return MUTEX_UNLOCKED
|
||||||
|
*/
|
||||||
|
mutex_t mutex_trylock(mutex_t *m){
|
||||||
|
uint32_t status = 0;
|
||||||
|
mutex_t old_lock = __ldrex(m); // get mutex value
|
||||||
|
// set mutex
|
||||||
|
status = __strex(MUTEX_LOCKED, m);
|
||||||
|
if(status == 0) __dmb();
|
||||||
|
else old_lock = MUTEX_LOCKED;
|
||||||
|
return old_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
53
F1/2.8TFT/sync.h
Normal file
53
F1/2.8TFT/sync.h
Normal 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
|
||||||
93
F1/2.8TFT/user_proto.c
Normal file
93
F1/2.8TFT/user_proto.c
Normal 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');
|
||||||
|
}
|
||||||
|
|
||||||
47
F1/2.8TFT/user_proto.h
Normal file
47
F1/2.8TFT/user_proto.h
Normal 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__
|
||||||
Loading…
x
Reference in New Issue
Block a user