From 115ac7159bc0106c46653501654e63fa44d9cea0 Mon Sep 17 00:00:00 2001 From: Andre Date: Wed, 2 Jan 2019 21:27:57 -0500 Subject: [PATCH] Emulator support --- .gitignore | 1 + Makefile | 1 + common.mk | 2 +- include/cortex.h | 469 ------------------------------------------- include/emulator.h | 114 +++++++++++ include/periph.h | 90 +++------ include/supervisor.h | 58 +----- run.sh | 17 ++ src/API.c | 8 +- src/auto.c | 1 + src/comm.c | 136 +------------ src/emulator.c | 1 + src/encoder.c | 101 +--------- src/fs.c | 22 +- src/i2c.c | 147 +------------- src/init.c | 3 + src/io.c | 148 -------------- src/kernel.c | 82 ++++++-- src/motorcontrol.c | 150 +------------- src/opcontrol.c | 8 +- src/supervisor.c | 166 ++++----------- src/system.c | 235 +++------------------- src/watchdog.c | 37 +--- src/wave.c | 56 +----- 24 files changed, 337 insertions(+), 1716 deletions(-) create mode 100644 include/emulator.h create mode 100755 run.sh create mode 100644 src/emulator.c diff --git a/.gitignore b/.gitignore index 4449c5c2..9c325f2a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ template/ .vscode/ compile_commands.json *.zip +.editorconfig diff --git a/Makefile b/Makefile index 591a25d4..2d320a29 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ ARCHIVE_TEXT_LIST:=$(subst $(SPACE),$(COMMA),$(notdir $(basename $(wildcard $(FW ifndef OUTBIN OUTNAME:=output endif + OUTBIN:=$(BINDIR)/$(OUTNAME).bin OUTELF:=$(BINDIR)/$(OUTNAME).elf diff --git a/common.mk b/common.mk index 9f67b49f..9521db86 100644 --- a/common.mk +++ b/common.mk @@ -3,7 +3,7 @@ DEVICE=VexCortex MFLAGS=-mthumb -mcpu=cortex-m3 -mlittle-endian CPPFLAGS=-Os -GCCFLAGS=-ffunction-sections -fsigned-char -fomit-frame-pointer -fsingle-precision-constant -fdiagnostics-color +GCCFLAGS=-g -ffunction-sections -fsigned-char -fomit-frame-pointer -fsingle-precision-constant -fdiagnostics-color WARNFLAGS+= diff --git a/include/cortex.h b/include/cortex.h index c1f62558..dd878a7f 100644 --- a/include/cortex.h +++ b/include/cortex.h @@ -272,42 +272,6 @@ typedef struct { __IO uint32_t PR; } EXTI_TypeDef; -// FLASH memory register access structure -typedef struct { - __IO uint32_t ACR; - // Key register - __IO uint32_t KEYR; - // Optional key register - __IO uint32_t OPTKEYR; - // Status register - __IO uint32_t SR; - // Configuration register - __IO uint32_t CR; - __IO uint32_t AR; - __IO uint32_t RESERVED; - __IO uint32_t OBR; - // Write protection register - __IO uint32_t WRPR; -} FLASH_TypeDef; - -// GPIO register access structure -typedef struct { - // Configuration register low - __IO uint32_t CRL; - // Configuration register high - __IO uint32_t CRH; - // Input data register - __IO uint32_t IDR; - // Output data register - __IO uint32_t ODR; - // Bit set register - __IO uint32_t BSRR; - // Bit reset register - __IO uint32_t BRR; - // Configuration lock register - __IO uint32_t LCKR; -} GPIO_TypeDef; - // Alternate I/O pin mapping register access structure typedef struct { // Event control register @@ -627,39 +591,6 @@ typedef struct { // Timer #7 #define TIM7_BASE (APB1PERIPH_BASE + 0x1400) #define TIM7 ((TIM_TypeDef*)TIM7_BASE) -// Window watchdog -#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00) -#define WWDG ((WWDG_TypeDef*)WWDG_BASE) -// Independent watchdog -#define IWDG_BASE (APB1PERIPH_BASE + 0x3000) -#define IWDG ((IWDG_TypeDef*)IWDG_BASE) -// SPI #2 -#define SPI2_BASE (APB1PERIPH_BASE + 0x3800) -#define SPI2 ((SPI_TypeDef*)SPI2_BASE) -// SPI #3 -#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00) -#define SPI3 ((SPI_TypeDef*)SPI3_BASE) -// USART #2 -#define USART2_BASE (APB1PERIPH_BASE + 0x4400) -#define USART2 ((USART_TypeDef*)USART2_BASE) -// USART #3 -#define USART3_BASE (APB1PERIPH_BASE + 0x4800) -#define USART3 ((USART_TypeDef*)USART3_BASE) -// UART #4 -#define UART4_BASE (APB1PERIPH_BASE + 0x4C00) -#define UART4 ((USART_TypeDef*)UART4_BASE) -// UART #5 -#define UART5_BASE (APB1PERIPH_BASE + 0x5000) -#define UART5 ((USART_TypeDef*)UART5_BASE) -// I2C #1 -#define I2C1_BASE (APB1PERIPH_BASE + 0x5400) -#define I2C1 ((I2C_TypeDef*)I2C1_BASE) -// I2C #2 -#define I2C2_BASE (APB1PERIPH_BASE + 0x5800) -#define I2C2 ((I2C_TypeDef*)I2C2_BASE) -// DAC -#define DAC_BASE (APB1PERIPH_BASE + 0x7400) -#define DAC ((DAC_TypeDef*)DAC_BASE) // Peripherals on APB2 // Alternate function I/O @@ -668,39 +599,9 @@ typedef struct { // External interrupt management #define EXTI_BASE (APB2PERIPH_BASE + 0x0400) #define EXTI ((EXTI_TypeDef*)EXTI_BASE) -// GPIO port A -#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) -#define GPIOA ((GPIO_TypeDef*)GPIOA_BASE) -// GPIO port B -#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) -#define GPIOB ((GPIO_TypeDef*)GPIOB_BASE) -// GPIO port C -#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) -#define GPIOC ((GPIO_TypeDef*)GPIOC_BASE) -// GPIO port D -#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) -#define GPIOD ((GPIO_TypeDef*)GPIOD_BASE) -// GPIO port E -#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) -#define GPIOE ((GPIO_TypeDef*)GPIOE_BASE) -// GPIO port F -#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00) -#define GPIOF ((GPIO_TypeDef*)GPIOF_BASE) -// GPIO port G -#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000) -#define GPIOG ((GPIO_TypeDef*)GPIOG_BASE) -// ADC #1 -#define ADC1_BASE (APB2PERIPH_BASE + 0x2400) -#define ADC1 ((ADC_TypeDef*)ADC1_BASE) -// ADC #2 -#define ADC2_BASE (APB2PERIPH_BASE + 0x2800) -#define ADC2 ((ADC_TypeDef*)ADC2_BASE) // Timer #1 #define TIM1_BASE (APB2PERIPH_BASE + 0x2C00) #define TIM1 ((TIM_TypeDef*)TIM1_BASE) -// SPI #1 -#define SPI1_BASE (APB2PERIPH_BASE + 0x3000) -#define SPI1 ((SPI_TypeDef*)SPI1_BASE) // Timer #8 #define TIM8_BASE (APB2PERIPH_BASE + 0x3400) #define TIM8 ((TIM_TypeDef*)TIM8_BASE) @@ -714,36 +615,6 @@ typedef struct { // Reset and clock control #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define RCC ((RCC_TypeDef*)RCC_BASE) -// DMA #1 -#define DMA1_BASE (AHBPERIPH_BASE + 0x0000) -#define DMA1 ((DMA_TypeDef*)DMA1_BASE) -#define DMA1_Channel1_BASE (AHBPERIPH_BASE + 0x0008) -#define DMA1_Channel1 ((DMA_Channel_TypeDef*)DMA1_Channel1_BASE) -#define DMA1_Channel2_BASE (AHBPERIPH_BASE + 0x001C) -#define DMA1_Channel2 ((DMA_Channel_TypeDef*)DMA1_Channel2_BASE) -#define DMA1_Channel3_BASE (AHBPERIPH_BASE + 0x0030) -#define DMA1_Channel3 ((DMA_Channel_TypeDef*)DMA1_Channel3_BASE) -#define DMA1_Channel4_BASE (AHBPERIPH_BASE + 0x0044) -#define DMA1_Channel4 ((DMA_Channel_TypeDef*)DMA1_Channel4_BASE) -#define DMA1_Channel5_BASE (AHBPERIPH_BASE + 0x0058) -#define DMA1_Channel5 ((DMA_Channel_TypeDef*)DMA1_Channel5_BASE) -#define DMA1_Channel6_BASE (AHBPERIPH_BASE + 0x006C) -#define DMA1_Channel6 ((DMA_Channel_TypeDef*)DMA1_Channel6_BASE) -#define DMA1_Channel7_BASE (AHBPERIPH_BASE + 0x0080) -#define DMA1_Channel7 ((DMA_Channel_TypeDef*)DMA1_Channel7_BASE) -// DMA #2 -#define DMA2_BASE (AHBPERIPH_BASE + 0x0400) -#define DMA2 ((DMA_TypeDef*)DMA2_BASE) -#define DMA2_Channel1_BASE (AHBPERIPH_BASE + 0x0408) -#define DMA2_Channel1 ((DMA_Channel_TypeDef*)DMA2_Channel1_BASE) -#define DMA2_Channel2_BASE (AHBPERIPH_BASE + 0x041C) -#define DMA2_Channel2 ((DMA_Channel_TypeDef*)DMA2_Channel2_BASE) -#define DMA2_Channel3_BASE (AHBPERIPH_BASE + 0x0430) -#define DMA2_Channel3 ((DMA_Channel_TypeDef*)DMA2_Channel3_BASE) -#define DMA2_Channel4_BASE (AHBPERIPH_BASE + 0x0444) -#define DMA2_Channel4 ((DMA_Channel_TypeDef*)DMA2_Channel4_BASE) -#define DMA2_Channel5_BASE (AHBPERIPH_BASE + 0x0458) -#define DMA2_Channel5 ((DMA_Channel_TypeDef*)DMA2_Channel5_BASE) // SysTick #define SysTick_BASE (SCS_BASE + 0x0010) #define SysTick ((SysTick_TypeDef*)SysTick_BASE) @@ -753,30 +624,6 @@ typedef struct { // System Control Block #define SCB_BASE (SCS_BASE + 0x0D00) #define SCB ((SCB_TypeDef*)SCB_BASE) -// Flash memory -#define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) -#define FLASH ((FLASH_TypeDef*)FLASH_R_BASE) - -// ADC defines -// ADC scan mode enable -#define ADC_CR1_SCAN ((uint32_t)0x00000100) - -// ADC on/off flag -#define ADC_CR2_ADON ((uint32_t)0x00000001) -// ADC continuous conversion enable/disable -#define ADC_CR2_CONT ((uint32_t)0x00000002) -// ADC calibration in progress? -#define ADC_CR2_CAL ((uint32_t)0x00000004) -// Reset ADC calibration -#define ADC_CR2_RSTCAL ((uint32_t)0x00000008) -// Enable ADC DMA requests -#define ADC_CR2_DMA ((uint32_t)0x00000100) -// Disables ADC external trigger -#define ADC_CR2_NOTRIG ((uint32_t)0x000E0000) -// Starts software conversion loop -#define ADC_CR2_SWSTART ((uint32_t)0x00500000) -// Temperature sensor and reference voltage enable -#define ADC_CR2_TSVREFE ((uint32_t)0x00800000) // Mapping defines // Remap I2C1 to PB8..PB9 @@ -792,257 +639,6 @@ typedef struct { // Remap TIM1 fully to Port E #define AFIO_MAPR_TIM1_REMAP_FULL ((uint32_t)0x000000C0) -// DAC defines -// DAC channel 1 enable/disable flag -#define DAC_CR_EN1 ((uint32_t)0x00000001) -// DAC channel 1 buffer disable flag -#define DAC_CR_BOFF1 ((uint32_t)0x00000002) -// DAC channel 1 trigger enable flag -#define DAC_CR_TEN1 ((uint32_t)0x00000004) -// DAC channel 1 DMA enable/disable flag -#define DAC_CR_DMAEN1 ((uint32_t)0x00001000) - -// DMA defines -// DMA channel enable -#define DMA_CCR_EN ((uint32_t)0x00000001) -// Transfer complete interrupt enable -#define DMA_CCR_TCIE ((uint32_t)0x00000002) -// Transfer halfway done interrupt enable -#define DMA_CCR_HTIE ((uint32_t)0x00000004) -// Peripheral to memory -#define DMA_CCR_SRC ((uint32_t)0x00000000) -// Memory to peripheral -#define DMA_CCR_DST ((uint32_t)0x00000010) -// Circular mode enable -#define DMA_CCR_CIRC ((uint32_t)0x00000020) -// Auto-increment peripheral address -#define DMA_CCR_PERIPHINC ((uint32_t)0x00000040) -// Auto-increment memory address -#define DMA_CCR_MEMINC ((uint32_t)0x00000080) -// Source size of byte -#define DMA_CCR_SRC_BYTE ((uint32_t)0x00000000) -// Source size of halfword -#define DMA_CCR_SRC_HWORD ((uint32_t)0x00000100) -// Source size of word -#define DMA_CCR_SRC_WORD ((uint32_t)0x00000200) -// Destination size of byte -#define DMA_CCR_DST_BYTE ((uint32_t)0x00000000) -// Destination size of halfword -#define DMA_CCR_DST_HWORD ((uint32_t)0x00000400) -// Destination size of word -#define DMA_CCR_DST_WORD ((uint32_t)0x00000800) -// Low priority transfer -#define DMA_CCR_PRI_LOW ((uint32_t)0x00000000) -// Medium priority transfer -#define DMA_CCR_PRI_MED ((uint32_t)0x00001000) -// High priority transfer -#define DMA_CCR_PRI_HIGH ((uint32_t)0x00002000) -// Very high priority transfer -#define DMA_CCR_PRI_MAX ((uint32_t)0x00003000) -// Memory-to-memory? -#define DMA_CCR_M2M ((uint32_t)0x00004000) - -// Global interrupt clear channel 1 -#define DMA_IFCR_CGIF1 ((uint32_t)0x00000001) -// Transfer complete interrupt clear channel 1 -#define DMA_IFCR_CTCIF1 ((uint32_t)0x00000002) -// Halfway complete interrupt clear channel 1 -#define DMA_IFCR_CHTIF1 ((uint32_t)0x00000004) -// Error flag clear channel 1 -#define DMA_IFCR_CTEIF1 ((uint32_t)0x00000008) -// Global interrupt clear channel 2 -#define DMA_IFCR_CGIF2 ((uint32_t)0x00000010) -// Transfer complete interrupt clear channel 2 -#define DMA_IFCR_CTCIF2 ((uint32_t)0x00000020) -// Halfway complete interrupt clear channel 2 -#define DMA_IFCR_CHTIF2 ((uint32_t)0x00000040) -// Error flag clear channel 2 -#define DMA_IFCR_CTEIF2 ((uint32_t)0x00000080) -// Global interrupt clear channel 3 -#define DMA_IFCR_CGIF3 ((uint32_t)0x00000100) -// Transfer complete interrupt clear channel 3 -#define DMA_IFCR_CTCIF3 ((uint32_t)0x00000200) -// Halfway complete interrupt clear channel 3 -#define DMA_IFCR_CHTIF3 ((uint32_t)0x00000400) -// Error flag clear channel 3 -#define DMA_IFCR_CTEIF3 ((uint32_t)0x00000800) -// Global interrupt clear channel 4 -#define DMA_IFCR_CGIF4 ((uint32_t)0x00001000) -// Transfer complete interrupt clear channel 4 -#define DMA_IFCR_CTCIF4 ((uint32_t)0x00002000) -// Halfway complete interrupt clear channel 4 -#define DMA_IFCR_CHTIF4 ((uint32_t)0x00004000) -// Error flag clear channel 4 -#define DMA_IFCR_CTEIF4 ((uint32_t)0x00008000) -// Global interrupt clear channel 5 -#define DMA_IFCR_CGIF5 ((uint32_t)0x00010000) -// Transfer complete interrupt clear channel 5 -#define DMA_IFCR_CTCIF5 ((uint32_t)0x00020000) -// Halfway complete interrupt clear channel 5 -#define DMA_IFCR_CHTIF5 ((uint32_t)0x00040000) -// Error flag clear channel 5 -#define DMA_IFCR_CTEIF5 ((uint32_t)0x00080000) -// Global interrupt clear channel 6 -#define DMA_IFCR_CGIF6 ((uint32_t)0x00100000) -// Transfer complete interrupt clear channel 6 -#define DMA_IFCR_CTCIF6 ((uint32_t)0x00200000) -// Halfway complete interrupt clear channel 6 -#define DMA_IFCR_CHTIF6 ((uint32_t)0x00400000) -// Error flag clear channel 6 -#define DMA_IFCR_CTEIF6 ((uint32_t)0x00800000) -// Global interrupt clear channel 7 -#define DMA_IFCR_CGIF7 ((uint32_t)0x01000000) -// Transfer complete interrupt clear channel 7 -#define DMA_IFCR_CTCIF7 ((uint32_t)0x02000000) -// Halfway complete interrupt clear channel 7 -#define DMA_IFCR_CHTIF7 ((uint32_t)0x04000000) -// Error flag clear channel 7 -#define DMA_IFCR_CTEIF7 ((uint32_t)0x08000000) - -// Global interrupt channel 1 -#define DMA_ISR_GIF1 ((uint32_t)0x00000001) -// Transfer complete interrupt channel 1 -#define DMA_ISR_TCIF1 ((uint32_t)0x00000002) -// Halfway complete interrupt channel 1 -#define DMA_ISR_HTIF1 ((uint32_t)0x00000004) -// Error flag channel 1 -#define DMA_ISR_TEIF1 ((uint32_t)0x00000008) -// Global interrupt channel 2 -#define DMA_ISR_GIF2 ((uint32_t)0x00000010) -// Transfer complete interrupt channel 2 -#define DMA_ISR_TCIF2 ((uint32_t)0x00000020) -// Halfway complete interrupt channel 2 -#define DMA_ISR_HTIF2 ((uint32_t)0x00000040) -// Error flag channel 2 -#define DMA_ISR_TEIF2 ((uint32_t)0x00000080) -// Global interrupt channel 3 -#define DMA_ISR_GIF3 ((uint32_t)0x00000100) -// Transfer complete interrupt channel 3 -#define DMA_ISR_TCIF3 ((uint32_t)0x00000200) -// Halfway complete interrupt channel 3 -#define DMA_ISR_HTIF3 ((uint32_t)0x00000400) -// Error flag channel 3 -#define DMA_ISR_TEIF3 ((uint32_t)0x00000800) -// Global interrupt channel 4 -#define DMA_ISR_GIF4 ((uint32_t)0x00001000) -// Transfer complete interrupt channel 4 -#define DMA_ISR_TCIF4 ((uint32_t)0x00002000) -// Halfway complete interrupt channel 4 -#define DMA_ISR_HTIF4 ((uint32_t)0x00004000) -// Error flag channel 4 -#define DMA_ISR_TEIF4 ((uint32_t)0x00008000) -// Global interrupt channel 5 -#define DMA_ISR_GIF5 ((uint32_t)0x00010000) -// Transfer complete interrupt channel 5 -#define DMA_ISR_TCIF5 ((uint32_t)0x00020000) -// Halfway complete interrupt channel 5 -#define DMA_ISR_HTIF5 ((uint32_t)0x00040000) -// Error flag channel 5 -#define DMA_ISR_TEIF5 ((uint32_t)0x00080000) -// Global interrupt channel 6 -#define DMA_ISR_GIF6 ((uint32_t)0x00100000) -// Transfer complete interrupt channel 6 -#define DMA_ISR_TCIF6 ((uint32_t)0x00200000) -// Halfway complete interrupt channel 6 -#define DMA_ISR_HTIF6 ((uint32_t)0x00400000) -// Error flag channel 6 -#define DMA_ISR_TEIF6 ((uint32_t)0x00800000) -// Global interrupt channel 7 -#define DMA_ISR_GIF7 ((uint32_t)0x01000000) -// Transfer complete interrupt channel 7 -#define DMA_ISR_TCIF7 ((uint32_t)0x02000000) -// Halfway complete interrupt channel 7 -#define DMA_ISR_HTIF7 ((uint32_t)0x04000000) -// Error flag channel 7 -#define DMA_ISR_TEIF7 ((uint32_t)0x08000000) - -// Flash memory defines -// Bits for Flash latency cycles -#define FLASH_ACR_LATENCY ((uint8_t)0x03) -// Two wait states for Flash access -#define FLASH_ACR_LATENCY_2 ((uint8_t)0x02) -// Prefetch buffer enable -#define FLASH_ACR_PRFTBE ((uint8_t)0x10) - -// Flash busy flag -#define FLASH_SR_BSY ((uint8_t)0x01) -// Flash programming error flag (write location not 0xFFFF to anything but 0x0000) -#define FLASH_SR_PGERR ((uint8_t)0x04) -// Write protection error (write location that is protected) -#define FLASH_SR_WRPRTERR ((uint8_t)0x10) -// End-of-operation flag -#define FLASH_SR_EOP ((uint8_t)0x20) - -// Programming mode enable -#define FLASH_CR_PG ((uint16_t)0x0001) -// Page erase mode enable -#define FLASH_CR_PER ((uint16_t)0x0002) -// Mass erase mode enable -#define FLASH_CR_MER ((uint16_t)0x0004) -// Start operation command bit -#define FLASH_CR_STRT ((uint16_t)0x0040) -// Lock FLASH command bit -#define FLASH_CR_LOCK ((uint16_t)0x0080) -// FLASH Error interrupt enable flag -#define FLASH_CR_ERRIE ((uint16_t)0x0400) -// FLASH complete interrupt enable flag -#define FLASH_CR_EOPIE ((uint16_t)0x1000) - -// I2C defines -// I2C enable -#define I2C_CR1_PE ((uint16_t)0x0001) -// Start-bit generation flag -#define I2C_CR1_START ((uint16_t)0x0100) -// Stop-bit generation flag -#define I2C_CR1_STOP ((uint16_t)0x0200) -// Acknowledge enable flag -#define I2C_CR1_ACK ((uint16_t)0x0400) -// Acknowledge position -#define I2C_CR1_POS ((uint16_t)0x0800) -// Software reset flag -#define I2C_CR1_SWRST ((uint16_t)0x8000) - -// I2C error interrupt enable -#define I2C_CR2_ITERREN ((uint16_t)0x0100) -// I2C event interrupt enable -#define I2C_CR2_ITEVTEN ((uint16_t)0x0200) -// I2C buffer interrupt enable -#define I2C_CR2_ITBUFEN ((uint16_t)0x0400) - -// Addressing mode flag -#define I2C_OAR1_ADDMODE ((uint16_t)0x8000) -// Dual addressing mode enable -#define I2C_OAR2_ENDUAL ((uint8_t)0x01) - -// Start bit flag -#define I2C_SR1_SB ((uint16_t)0x0001) -// Address-sent flag -#define I2C_SR1_ADDR ((uint16_t)0x0002) -// Transfer finished flag -#define I2C_SR1_BTF ((uint16_t)0x0004) -// Receiver data full flag -#define I2C_SR1_RXNE ((uint16_t)0x0040) -// Transmitter data empty flag -#define I2C_SR1_TXE ((uint16_t)0x0080) -// Bus error flag -#define I2C_SR1_BERR ((uint16_t)0x0100) -// Arbitration lost flag -#define I2C_SR1_ARLO ((uint16_t)0x0200) -// Acknowledge failure flag -#define I2C_SR1_AF ((uint16_t)0x0400) -// Timeout flag -#define I2C_SR1_OVR ((uint16_t)0x0800) - -// Master/slave flag -#define I2C_SR2_MSL ((uint16_t)0x0001) -// Bus busy flag -#define I2C_SR2_BUSY ((uint16_t)0x0002) -// Transmitter/receiver flag -#define I2C_SR2_TRA ((uint16_t)0x0004) - -// Fast mode selection -#define I2C_CCR_FS ((uint16_t)0x8000) - // RCC defines // Enable HSE #define RCC_CR_HSEON ((uint32_t)0x00010000) @@ -1258,30 +854,6 @@ typedef struct { // Enable illegal instruction fault handler #define SCB_SHCSR_USGFAULTENA ((uint32_t)0x00040000) -// SPI defines -// CPHA = 1 (even edges) -#define SPI_CR1_CPHA_1 ((uint16_t)0x0001) -// CPOL = 1 (active low clock) -#define SPI_CR1_CPOL_1 ((uint16_t)0x0002) -// Baud rate 32 -#define SPI_CR1_DIV32 ((uint16_t)0x0020) -// SPI enable -#define SPI_CR1_SPE ((uint16_t)0x0040) -// SPI master mode -#define SPI_CR1_MSTR ((uint16_t)0x0104) -// Software slave selection -#define SPI_CR1_NSS_SOFT ((uint16_t)0x0200) -// 16-bit data size -#define SPI_CR1_16BIT ((uint16_t)0x0800) - -// Receive buffer full interrupt enable -#define SPI_CR2_RXNEIE ((uint16_t)0x0040) - -// Transmit data empty flag -#define SPI_SR_TXE ((uint16_t)0x0002) -// Receive buffer full flag -#define SPI_SR_RXNE ((uint16_t)0x0001) - // SysTick defines // SysTick enable #define SysTick_CTRL_ENABLE ((uint32_t)0x00000001) @@ -1326,47 +898,6 @@ typedef struct { #define TIM_EGR_UG ((uint16_t)0x0001) -// USART defines -// Read data register full flag -#define USART_SR_RXNE ((uint16_t)0x0020) -// Transmit data register empty flag -#define USART_SR_TXE ((uint16_t)0x0080) - -// Reciever enable flag -#define USART_CR1_RE ((uint16_t)0x0004) -// Transmitter enable flag -#define USART_CR1_TE ((uint16_t)0x0008) -// Receive interrupt enable flag -#define USART_CR1_RXNEIE ((uint16_t)0x0020) -// Transmit data register empty interrupt enable flag -#define USART_CR1_TXEIE ((uint16_t)0x0080) -// Parity selection -#define USART_CR1_PS ((uint16_t)0x0200) -// Parity control -#define USART_CR1_PCE ((uint16_t)0x0400) -// Word length flag -#define USART_CR1_M ((uint16_t)0x1000) -// USART enable flag -#define USART_CR1_UE ((uint16_t)0x2000) - -// Last bit-clock send flag -#define USART_CR2_LBCL ((uint16_t)0x0100) -// Clock phase -#define USART_CR2_CPHA ((uint16_t)0x0200) -// Clock polarity -#define USART_CR2_CPOL ((uint16_t)0x0400) -// Clock enable -#define USART_CR2_CLKEN ((uint16_t)0x0800) -// Stop bit 0 -#define USART_CR2_STOP0 ((uint16_t)0x1000) -// Stop bit 1 -#define USART_CR2_STOP1 ((uint16_t)0x2000) - -// Flow control RTS enable -#define USART_CR3_RTSE ((uint16_t)0x0100) -// Flow control CTS enable -#define USART_CR3_CTSE ((uint16_t)0x0200) - // Disables FAULT interrupts static inline void __disable_fault_irq() { asm volatile ("cpsid f"); } // Disables interrupts diff --git a/include/emulator.h b/include/emulator.h new file mode 100644 index 00000000..48dc279f --- /dev/null +++ b/include/emulator.h @@ -0,0 +1,114 @@ +#ifndef INC_EMULATOR_H +#define INC_EMULATOR_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define __IO volatile + +typedef struct { + // Control register + __IO uint32_t CR; + // Args + __IO uint32_t A1; + __IO uint32_t A2; + __IO uint32_t A3; + // Results + __IO uint32_t R1; + __IO uint32_t R2; + __IO uint32_t R3; + __IO uint32_t R4; +} EMULATOR_TypeDef; + +#define EMULATOR ((EMULATOR_TypeDef*)0x40021400) + +inline int emuCall(uint16_t mod, uint16_t func, uint32_t a1, uint32_t a2, uint32_t a3) { + _enterCritical(); + EMULATOR->A1 = a1; + EMULATOR->A2 = a2; + EMULATOR->A3 = a3; + EMULATOR->CR = func | (mod << 16); + int out = EMULATOR->R1; + _exitCritical(); + return out; +} + +// Redundant EMUCONCAT to evaluate EMUMODNAME +#define EMUCONCAT2(x,y) Emu ## x ## _ ## y +#define EMUCONCAT(x,y) EMUCONCAT2(x,y) +#define EMUFNAME(x) EMUCONCAT(EMUMODNAME,x) + +#define EMUDEFINEFUNC(id, fname) inline int EMUFNAME(fname)() { return emuCall(EMUMODID, id, 0, 0, 0); } +#define EMUDEFINEFUNC1(id, fname, a1type, a1) inline int EMUFNAME(fname)(a1type a1) { return emuCall(EMUMODID, id, (int)a1, 0, 0); } +#define EMUDEFINEFUNC2(id, fname, a1type, a1, a2type, a2) inline int EMUFNAME(fname)(a1type a1, a2type a2) { return emuCall(EMUMODID, id, (int)a1, (int)a2, 0); } +#define EMUDEFINEFUNC3(id, fname, a1type, a1, a2type, a2, a3type, a3) inline int EMUFNAME(fname)(a1type a1, a2type a2, a3type a3) { return emuCall(EMUMODID, id, (int)a1, (int)a2, (int)a3); } + +#define EMUMODNAME Serial +#define EMUMODID 0 +EMUDEFINEFUNC3(0, init, int, port, int, baud, int, flags); +EMUDEFINEFUNC1(1, shutdown, int, port); +EMUDEFINEFUNC2(2, putc, int, port, int, c); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME FS +#define EMUMODID 1 +EMUDEFINEFUNC(0, programOn); +EMUDEFINEFUNC(1, programOff); +EMUDEFINEFUNC1(2, erasePage, int, page); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME I2C +#define EMUMODID 2 +EMUDEFINEFUNC3(0, startRead, int, addr, void*, data, int, count); +EMUDEFINEFUNC3(1, startWrite, int, addr, void*, data, int, count); +EMUDEFINEFUNC1(2, setAddr, int, addr); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME GPIO +#define EMUMODID 3 +EMUDEFINEFUNC1(0, ADCInit, uint32_t, data); +EMUDEFINEFUNC2(1, SetDir, int, port, int, mode); +EMUDEFINEFUNC1(2, GetInput, int, port); +EMUDEFINEFUNC1(3, GetOutput, int, port); +EMUDEFINEFUNC2(4, SetOutput, int, port, int, value); +EMUDEFINEFUNC2(5, SetInterrupt, int, port, int, edges); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME Motor +#define EMUMODID 4 +EMUDEFINEFUNC1(0, get, int, channel); +EMUDEFINEFUNC2(1, set, int, channel, int, value); +EMUDEFINEFUNC(2, stop); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME Comp +#define EMUMODID 5 +EMUDEFINEFUNC(0, init); +EMUDEFINEFUNC(1, enableStandalone); +EMUDEFINEFUNC1(2, setName, char*, name); +EMUDEFINEFUNC1(3, getStatus, void*, buff); +#undef EMUMODNAME +#undef EMUMODID + +#define EMUMODNAME System +#define EMUMODID 6 +EMUDEFINEFUNC(0, exit); +EMUDEFINEFUNC(1, break); +#undef EMUMODNAME +#undef EMUMODID + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/periph.h b/include/periph.h index 55e46a5a..2687f87f 100644 --- a/include/periph.h +++ b/include/periph.h @@ -18,6 +18,7 @@ #include #include #include +#include // Begin C++ extern to C #ifdef __cplusplus @@ -55,38 +56,38 @@ extern "C" { // Pinning definitions for ioSetDirection // Digital inputs 1-12 -#define PIN_DIGITAL_1 GPIOE, 9 -#define PIN_DIGITAL_2 GPIOE, 11 -#define PIN_DIGITAL_3 GPIOC, 6 -#define PIN_DIGITAL_4 GPIOC, 7 -#define PIN_DIGITAL_5 GPIOE, 13 -#define PIN_DIGITAL_6 GPIOE, 14 -#define PIN_DIGITAL_7 GPIOE, 8 -#define PIN_DIGITAL_8 GPIOE, 10 -#define PIN_DIGITAL_9 GPIOE, 12 -#define PIN_DIGITAL_10 GPIOE, 7 -#define PIN_DIGITAL_11 GPIOD, 0 -#define PIN_DIGITAL_12 GPIOD, 1 +#define PIN_DIGITAL_1 1 +#define PIN_DIGITAL_2 2 +#define PIN_DIGITAL_3 3 +#define PIN_DIGITAL_4 4 +#define PIN_DIGITAL_5 5 +#define PIN_DIGITAL_6 6 +#define PIN_DIGITAL_7 7 +#define PIN_DIGITAL_8 8 +#define PIN_DIGITAL_9 9 +#define PIN_DIGITAL_10 10 +#define PIN_DIGITAL_11 11 +#define PIN_DIGITAL_12 12 // Speaker port (NOT 5V tolerant!) -#define PIN_SP GPIOA, 4 +#define PIN_SP 0 // Analog inputs 1-8 -#define PIN_ANALOG_1 GPIOA, 0 -#define PIN_ANALOG_2 GPIOA, 1 -#define PIN_ANALOG_3 GPIOA, 2 -#define PIN_ANALOG_4 GPIOA, 3 -#define PIN_ANALOG_5 GPIOC, 2 -#define PIN_ANALOG_6 GPIOC, 3 -#define PIN_ANALOG_7 GPIOC, 0 -#define PIN_ANALOG_8 GPIOC, 1 +#define PIN_ANALOG_1 13 +#define PIN_ANALOG_2 14 +#define PIN_ANALOG_3 15 +#define PIN_ANALOG_4 16 +#define PIN_ANALOG_5 17 +#define PIN_ANALOG_6 18 +#define PIN_ANALOG_7 19 +#define PIN_ANALOG_8 20 // Analog #9 is on the speaker port (NOT 5V tolerant!) #define PIN_ANALOG_9 PIN_SP // Communications ports (these pins are NOT 5V tolerant!) -#define PIN_UART1_TX GPIOD, 5 -#define PIN_UART1_RX GPIOD, 6 -#define PIN_UART2_TX GPIOC, 10 -#define PIN_UART2_RX GPIOC, 11 -#define PIN_I2C1_SCL GPIOB, 8 -#define PIN_I2C1_SDA GPIOB, 9 +#define PIN_UART1_TX 21 +#define PIN_UART1_RX 22 +#define PIN_UART2_TX 23 +#define PIN_UART2_RX 24 +#define PIN_I2C1_SCL 25 +#define PIN_I2C1_SDA 26 // Constants for ioSetInterrupt - Which edges to register interrupt? #define INTERRUPT_EDGE_RISING 1 @@ -151,11 +152,6 @@ typedef void * Ultrasonic; // Gyro information is stored as an opaque pointer to a structure in memory typedef void * Gyro; -// Pin lookup tables -extern const uint8_t _adcChannelTable[BOARD_NR_ADC_PINS]; -extern const GPIO_TypeDef* const _pinLookupTable[BOARD_NR_GPIO_PINS]; -extern const uint8_t _pinIndexTable[BOARD_NR_GPIO_PINS]; - // Sensor status tables extern Sensor_TypeDef _sensorState[BOARD_NR_DIGITAL_IO]; extern Analog_TypeDef _analogState[BOARD_NR_ADC_PINS]; @@ -199,33 +195,7 @@ static INLINE void _highResSchedule(uint8_t channel, uint16_t diff) { } } -// ioGetInput - Gets the digital value (1 or 0) of a pin configured as a digital input -static INLINE bool ioGetInput(GPIO_TypeDef* port, uint32_t pin) { - // Shift right that many bits, then mask everything but the ones - return ((port->IDR >> (pin & 0x0F)) & 0x01) != 0; -} - -// ioGetOutput - Gets the current value (1 or 0) of a pin configured as a digital output -static INLINE bool ioGetOutput(GPIO_TypeDef* port, uint32_t pin) { - // Shift right that many bits, then mask everything but the ones - return ((port->ODR >> (pin & 0x0F)) & 0x01) != 0; -} - -// ioSetOutput - Sets the digital value (1 or 0) of a pin configured as a digital output -static INLINE void ioSetOutput(GPIO_TypeDef* port, uint32_t pin, bool value) { - if (value) - // Atomic bit set - port->BSRR = ((uint32_t)0x00000001) << (pin & 0x0F); - else - // Atomic bit reset - port->BRR = ((uint32_t)0x00000001) << (pin & 0x0F); -} - // Library functions -// adcOff - Stops the ADC, use before reconfiguring -void adcOff(); -// adcOn - Starts the ADC -void adcOn(); // adcRead - Reads a channel 0-15 from the ADC uint16_t adcRead(uint32_t channel); // adcSetChannels - Sets the channels sampled by the ADC (ADC must be off!) @@ -281,10 +251,6 @@ void imeShutdown(); // ioClearInterrupt - Disables interrupts on the specified pin void ioClearInterrupt(unsigned char pin); -// ioMultiSetDirection - Configures the specified pins in the bit mask to the given type -void ioMultiSetDirection(GPIO_TypeDef* port, uint16_t pinMask, uint32_t type); -// ioSetDirection - Configures the pin as an input or output with a variety of settings -void ioSetDirection(GPIO_TypeDef* port, uint32_t pin, uint32_t type); // ioSetInterrupt - Sets up an interrupt to occur on the specified pin, and resets count & time void ioSetInterrupt(unsigned char pin, unsigned char edges, InterruptHandler handler); diff --git a/include/supervisor.h b/include/supervisor.h index 76cbef8e..a5315c67 100644 --- a/include/supervisor.h +++ b/include/supervisor.h @@ -27,22 +27,14 @@ extern "C" { typedef struct { // Joystick axes volatile uint8_t axis[6]; - // Appears to be always 0x7F - volatile uint8_t RESERVED0; // Joystick button #5 and 6 volatile uint8_t button56; // Joystick button #7 and 8 volatile uint8_t button78; - // Appears to be always zero - volatile uint8_t RESERVED1[3]; -} Joystick_TypeDef; +} __attribute__((packed)) Joystick_TypeDef; // Structure representing the 32 bytes of data received from the supervisor typedef struct { - // Operation key, should be C917 during normal operation - volatile uint16_t key; - // Determines what type of information should be sent - volatile uint8_t inMode; // Game status volatile uint8_t gameStatus; // Main battery "voltage" @@ -51,40 +43,16 @@ typedef struct { volatile uint8_t backupBattery; // Joysticks volatile Joystick_TypeDef joystick[2]; - // Version - volatile uint8_t version; - volatile uint8_t RESERVED; -} Supervisor_RecvTypeDef; - -// Structure representing the 32 bytes of data sent to the supervisor -typedef struct { - // Should always be the magic number 0xC917 - volatile uint16_t key; - // Response mode to the input mode - volatile uint8_t mode; - // Additional flags (brake mode!?) - volatile uint8_t flags; - volatile uint8_t RESERVED0; - // Unsure - volatile uint8_t outMode; - // Data values (motor PWM or team name) - volatile uint8_t data[8]; - volatile uint32_t RESERVED1[4]; - // Version - volatile uint8_t version; - // Packet number - volatile uint8_t packetNum; -} Supervisor_TransTypeDef; +} __attribute__((packed)) Supervisor_RecvTypeDef; // Supervisor flags extern volatile uint16_t svFlags; // Buffers for SPI communications (16 words = 32 bytes) -extern volatile uint16_t spiBufferRX[16], spiBufferTX[16]; +extern volatile uint16_t spiBufferRX[16]; // Team name to report when asked for configuration extern char svTeamName[8]; // Alias buffers to structures for easy lookup #define SV_IN ((Supervisor_RecvTypeDef*)(&spiBufferRX)) -#define SV_OUT ((Supervisor_TransTypeDef*)(&spiBufferTX)) // Autonomous flag bit #define SV_AUTONOMOUS ((uint16_t)0x0004) @@ -95,19 +63,6 @@ extern char svTeamName[8]; // FMS enabled bit #define SV_FMS ((uint16_t)0x0008) -// svSetAllData - Loads data into all eight output registers to be sent to the supervisor -static INLINE void svSetAllData(uint8_t value) { - uint32_t i; - for (i = 0; i < 8; i++) - SV_OUT->data[i] = value; -} - -// svGetOutputData - Reads data from a specified output register that would be sent to the -// supervisor; intended for motorGet() call support -static INLINE uint8_t svGetOutputData(uint8_t index) { - return SV_OUT->data[index]; -} - // svGetBackupBattery - Gets the backup battery voltage in millivolts, or 0 if not connected static INLINE uint32_t svGetBackupBattery() { uint32_t volts = ((uint32_t)SV_IN->backupBattery) * 59; @@ -196,11 +151,6 @@ static INLINE uint8_t svIsOnline() { return (svFlags & SV_FMS) >> 3; } -// svSetData - Loads data into a specified output register to be sent to the supervisor -static INLINE void svSetData(uint8_t index, uint8_t value) { - SV_OUT->data[index] = value; -} - // svSetTeamName - Changes the team name reported to the supervisor static INLINE void svSetTeamName(const char *name) { char c; uint8_t i; @@ -219,8 +169,6 @@ static INLINE void svSetTeamName(const char *name) { void svInit(); // svSetAllData - Loads data into all eight output registers to be sent to the supervisor void svSetAllData(uint8_t value); -// svStartTransfer - Begins a supervisor transfer -void svStartTransfer(); // svSynchronize - Waits for the supervisor to synchronize, then reads the game status bits void svSynchronize(); diff --git a/run.sh b/run.sh new file mode 100755 index 00000000..abc1c197 --- /dev/null +++ b/run.sh @@ -0,0 +1,17 @@ +EMU_ARGS="" + +while getopts ":d" opt; do + case ${opt} in + d ) + EMU_ARGS="$EMU_ARGS -S -s";; + esac +done + +~/git/qemu_stm32/build/arm-softmmu/qemu-system-arm $EMU_ARGS -nographic -monitor none -serial stdio -machine vex-cortex -kernel bin/output.bin 2> >(\ + while read line; do + echo -e "\e[01;31m$(echo -e "$line" | tr -s "[:print:]\n")\e[0m" >&2; + if [[ $line == *"R15="* ]]; then + echo -e "\n\e[34m$(addr2line -e bin/output.elf `echo $line | sed -n "s/^.*R15=\s*\(\S*\).*$/\1/p"`)\e[0m\n"; + fi + done +) diff --git a/src/API.c b/src/API.c index e815fe61..9d972cc2 100644 --- a/src/API.c +++ b/src/API.c @@ -16,6 +16,7 @@ #include #include #include +#include // Structure for helping with taskRunLoop() typedef struct { @@ -126,7 +127,8 @@ void delayMicroseconds(const unsigned long time) { bool digitalRead(unsigned char pin) { if (pin >= BOARD_NR_GPIO_PINS) return 0; - return ioGetInput((GPIO_TypeDef*)_pinLookupTable[pin], (uint8_t)_pinIndexTable[pin]); + + return EmuGPIO_GetInput(pin); } // digitalWrite - Sets the digital value (1 or 0) of a pin configured as a digital output @@ -135,7 +137,7 @@ void digitalWrite(unsigned char pin, bool value) { // is needed to set initial solenoid states in initializeIO() when enabled/disabled is // undefined. if (pin < BOARD_NR_GPIO_PINS) - ioSetOutput((GPIO_TypeDef*)_pinLookupTable[pin], (uint8_t)_pinIndexTable[pin], value); + EmuGPIO_SetOutput(pin, value); } // isAutonomous - Checks to see if the system is in autonomous mode @@ -223,7 +225,7 @@ void motorStopAll() { // pinMode - Configures the pin as an input or output with a variety of settings void pinMode(unsigned char pin, unsigned char mode) { if (pin < BOARD_NR_GPIO_PINS) - ioSetDirection((GPIO_TypeDef*)_pinLookupTable[pin], (uint8_t)_pinIndexTable[pin], mode); + EmuGPIO_SetDir(pin, mode); } // powerLevelBackup - Get backup battery voltage in millivolts, or 0 if not connected diff --git a/src/auto.c b/src/auto.c index afb6923e..0d8e004f 100644 --- a/src/auto.c +++ b/src/auto.c @@ -24,4 +24,5 @@ * so, the robot will await a switch to another mode or disable/enable cycle. */ void autonomous() { + printf("autonomous started\n"); } diff --git a/src/comm.c b/src/comm.c index 8b389c90..b28b0de2 100644 --- a/src/comm.c +++ b/src/comm.c @@ -18,6 +18,7 @@ #include #include #include +#include // LCD backlight on #define LCD_BACKLIGHT ((uint8_t)0x02) @@ -169,19 +170,7 @@ char* fgets(char *str, int num, PROS_FILE *stream) { int fputc(int value, PROS_FILE *stream) { uint32_t snew = (uint32_t)stream - 1; if (snew < 3) { - SerialPort_TypeDef *ser = &usart[snew]; - _waitForSpace(ser); - // Jam a byte onto the head - _queueByte(&(ser->tx), (char)value); - if (snew == 0) - // Enable USART2 TXE interrupts - USART2->CR1 |= USART_CR1_TXEIE; - else if (snew == 1) - // Enable USART3 TXE interrupts - USART3->CR1 |= USART_CR1_TXEIE; - else if (snew == 2) - // Enable USART1 TXE interrupts - USART1->CR1 |= USART_CR1_TXEIE; + EmuSerial_putc(snew, value); } #ifndef NO_FILESYSTEM else @@ -229,31 +218,7 @@ int putchar(int value) { } // ISR_USART1 - Buffered character I/O handler for debug communications -void ISR_USART1() { - char value; - bool cs = false; - SerialPort_TypeDef *ser = &usart[2]; - if (USART1->SR & USART_SR_RXNE) { - // Read to clear the flag - value = (char)USART1->DR; - // Buffer it up, if it's not full to the brim - if (!_isBufferFull(&(ser->rx))) - _queueByte(&(ser->rx), value); - // Notify any receivers - semaphoreGiveISR(ser->readLock, &cs); - } - if (USART1->SR & USART_SR_TXE) { - if (_isBufferEmpty(&(ser->tx))) - // Nothing to send, disable interrupt - USART1->CR1 &= ~USART_CR1_TXEIE; - else { - value = _pullByte(&(ser->tx)); - USART1->DR = value; - } - } - if (cs) - _taskYield(); -} +void ISR_USART1() {} // Hardware not attached // lcdButtonProcess - Processes the VEX LCD buttons static void lcdButtonProcess(char value, uint32_t index) { @@ -280,66 +245,10 @@ static void lcdButtonProcess(char value, uint32_t index) { } // ISR_USART2 - Buffered character I/O handler for UART port 1 -void ISR_USART2() { - char value; - bool cs = false; - SerialPort_TypeDef *ser = &usart[0]; - if (USART2->SR & USART_SR_RXNE) { - // Read to clear the flag - value = (char)USART2->DR; - if (lcd[0].flags & LCD_ACTIVE) - lcdButtonProcess(value, 0); - else { - // Buffer it up, if it's not full to the brim - if (!_isBufferFull(&(ser->rx))) - _queueByte(&(ser->rx), value); - // Notify any receivers - semaphoreGiveISR(ser->readLock, &cs); - } - } - if (USART2->SR & USART_SR_TXE) { - if (_isBufferEmpty(&(ser->tx))) - // Nothing to send, disable interrupt - USART2->CR1 &= ~USART_CR1_TXEIE; - else { - value = _pullByte(&(ser->tx)); - USART2->DR = value; - } - } - if (cs) - _taskYield(); -} +void ISR_USART2() {} // Hardware not attached // ISR_USART3 - Buffered character I/O handler for UART port 2 -void ISR_USART3() { - char value; - bool cs = false; - SerialPort_TypeDef *ser = &usart[1]; - if (USART3->SR & USART_SR_RXNE) { - // Read to clear the flag - value = (char)USART3->DR; - if (lcd[1].flags & LCD_ACTIVE) - lcdButtonProcess(value, 1); - else { - // Buffer it up, if it's not full to the brim - if (!_isBufferFull(&(ser->rx))) - _queueByte(&(ser->rx), value); - // Notify any receivers - semaphoreGiveISR(ser->readLock, &cs); - } - } - if (USART3->SR & USART_SR_TXE) { - if (_isBufferEmpty(&(ser->tx))) - // Nothing to send, disable interrupt - USART3->CR1 &= ~USART_CR1_TXEIE; - else { - value = _pullByte(&(ser->tx)); - USART3->DR = value; - } - } - if (cs) - _taskYield(); -} +void ISR_USART3() {} // Hardware not attached // lcdClear - Clears the screen void lcdClear(PROS_FILE *lcdPort) { @@ -511,44 +420,17 @@ void usartFlushBuffers() { // usartInit - Initialize the specified USART interface with the given connection parameters // The interface argument can be 1 or 2 to specify UART1 and UART2 respectively void usartInit(PROS_FILE *port, unsigned int baud, unsigned int flags) { - // Determine correct USART - USART_TypeDef *base; - if (port == uart1) - base = USART2; - else if (port == uart2) - base = USART3; - else + if (port != uart1 && port != uart2) // Invalid interface return; _enterCritical(); - { - base->CR1 = 0; - // Flush buffers - if (port == uart1) { - usart[0].tx.tail = usart[0].tx.head; - usart[0].rx.tail = usart[0].rx.head; - } else { - usart[1].tx.tail = usart[1].tx.head; - usart[1].rx.tail = usart[1].rx.head; - } - // Configure base registers - base->CR2 = flags & (USART_CR2_STOP0 | USART_CR2_STOP1); - // Turn on USART - base->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_TE | USART_CR1_UE | - (flags & (USART_CR1_PCE | USART_CR1_PS | USART_CR1_M)); - base->CR3 = (uint16_t)0; - // Set baud rate - uint32_t brr = 225000000 / baud, mod = brr / 100, fracDiv = brr - (100 * mod); - base->BRR = (uint16_t)(mod << 4) | (uint16_t)((((fracDiv << 4) + 50) / 100) & 0xF); - } + EmuSerial_init(port == uart1 ? 1 : 2, baud, flags); _exitCritical(); } // usartShutdown - Disable the specified USART interface void usartShutdown(PROS_FILE *usart) { // Disable transmitter, receiver, clock, and interrupts - if (usart == uart1) - USART2->CR1 = (uint16_t)0; - else if (usart == uart2) - USART3->CR1 = (uint16_t)0; + if (usart != uart1 && usart != uart2) return; + EmuSerial_shutdown((int) usart); } diff --git a/src/emulator.c b/src/emulator.c new file mode 100644 index 00000000..a8633c68 --- /dev/null +++ b/src/emulator.c @@ -0,0 +1 @@ +#include diff --git a/src/encoder.c b/src/encoder.c index 6aa4cb24..cf29490d 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -153,11 +153,7 @@ void ioClearInterrupt(unsigned char pin) { // Avoid having the OS swap this out _enterCritical(); { - uint32_t mask = (uint32_t)1 << _pinIndexTable[pin + 1]; - // Clear pending interrupt - EXTI->PR |= mask; - // Mask interrupt - EXTI->IMR &= ~mask; + EmuGPIO_SetInterrupt(pin, 0); } _exitCritical(); } @@ -171,30 +167,10 @@ void ioSetInterrupt(unsigned char pin, unsigned char edges, InterruptHandler han // Avoid having the OS swap this out during init _enterCritical(); { - // In range, start by masking interrupt if enabled - uint32_t mask = (uint32_t)1 << _pinIndexTable[pin + 1], temp; - EXTI->IMR &= ~mask; // Configure freely, we won't have an issue here since interrupt is masked Sensor_TypeDef *state = &_sensorState[pin]; state->eventTrigger = handler; - // Falling edge configuration - temp = EXTI->FTSR; - if (edges & INTERRUPT_EDGE_FALLING) - temp |= mask; - else - temp &= ~mask; - EXTI->FTSR = temp; - // Rising edge configuration - temp = EXTI->RTSR; - if (edges & INTERRUPT_EDGE_RISING) - temp |= mask; - else - temp &= ~mask; - EXTI->RTSR = temp; - // Clear pending interrupt - EXTI->PR |= mask; - // Unmask interrupt to start monitoring - EXTI->IMR |= mask; + EmuGPIO_SetInterrupt(pin, edges); } _exitCritical(); } @@ -207,75 +183,10 @@ static INLINE void triggerEXTI(uint32_t pin) { handler(pin + 1); } -// External interrupts all Px0 pins (PD0/Digital 11) IRQ ISR_EXTI0() { - // We assume that this can only fire if unmasked (therefore, wanted) - triggerEXTI(10); - EXTI->PR = (uint32_t)0x0001; + triggerEXTI(EMULATOR->R1); } -// External interrupts all Px1 pins (PD1/Digital 12) -IRQ ISR_EXTI1() { - // We assume that this can only fire if unmasked (therefore, wanted) - triggerEXTI(11); - EXTI->PR = (uint32_t)0x0002; -} - -// External interrupts all Px5-Px9 pins -// (PC6/Digital 3, PC7/Digital 4, PE8/Digital 7, PE9/Digital 1) -IRQ ISR_EXTI9_5() { - uint32_t pending = EXTI->PR, reset = 0; - if (pending & (uint32_t)0x0040) { - // PC6 fired - triggerEXTI(2); - reset |= (uint32_t)0x0040; - } - if (pending & (uint32_t)0x0080) { - // PC7 fired - triggerEXTI(3); - reset |= (uint32_t)0x0080; - } - if (pending & (uint32_t)0x0100) { - // PE8 fired - triggerEXTI(6); - reset |= (uint32_t)0x0100; - } - if (pending & (uint32_t)0x0200) { - // PE9 fired - triggerEXTI(0); - reset |= (uint32_t)0x0200; - } - EXTI->PR = reset; -} - -// External interrupts all Px10-Px15 pins -// (PE10/Digital 8, PE11/Digital 2, PE12/Digital 9, PE13/Digital 5, PE14/Digital 6) -IRQ ISR_EXTI15_10() { - uint32_t pending = EXTI->PR, reset = 0; - if (pending & (uint32_t)0x0400) { - // PE10 fired - triggerEXTI(7); - reset |= (uint32_t)0x0400; - } - if (pending & (uint32_t)0x0800) { - // PE11 fired - triggerEXTI(1); - reset |= (uint32_t)0x0800; - } - if (pending & (uint32_t)0x1000) { - // PE12 fired - triggerEXTI(8); - reset |= (uint32_t)0x1000; - } - if (pending & (uint32_t)0x2000) { - // PE13 fired - triggerEXTI(4); - reset |= (uint32_t)0x2000; - } - if (pending & (uint32_t)0x4000) { - // PE14 fired - triggerEXTI(5); - reset |= (uint32_t)0x4000; - } - EXTI->PR = reset; -} +IRQ ISR_EXTI1() {} +IRQ ISR_EXTI9_5() {} +IRQ ISR_EXTI15_10() {} diff --git a/src/fs.c b/src/fs.c index e8d6b1d5..15d838d2 100644 --- a/src/fs.c +++ b/src/fs.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef NO_FILESYSTEM @@ -33,44 +34,29 @@ static INLINE void * _fs_pointer(const uint32_t page) { * Enable programming mode for the file system. */ static void _fs_prgm_on() { - FLASH->KEYR = 0x45670123; - FLASH->KEYR = 0xCDEF89AB; + EmuFS_programOn(); } /** * Disable programming mode for the file system. */ static void _fs_prgm_off() { - FLASH->CR = FLASH_CR_LOCK; + EmuFS_programOff(); } /** * Erase a page of memory. */ static void _fs_erase_page(uint32_t page) { - FLASH->CR = FLASH_CR_PER; - // Select page - FLASH->AR = (uint32_t)_fs_pointer(page); - // Start operation - FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT; - // Stall until BSY is reset (there is no sense sleeping here as IRQs cannot run while - // the erase is in progress) - while (FLASH->SR & FLASH_SR_BSY); - // Verify erasure? + EmuFS_erasePage(page); } /** * Program a (half)word to memory. */ static void _fs_prgm_word(uint32_t page, uint32_t offs, uint16_t value) { - FLASH->CR = FLASH_CR_PG; - // Ensure offs is even - //offs &= ~0x01; - // Select address by computing an offset from the desired page uint8_t *addr = (uint8_t*)_fs_pointer(page) + offs; *((uint16_t *)addr) = value; - // Stall until BSY is reset - while (FLASH->SR & FLASH_SR_BSY); } // Flags for file status diff --git a/src/i2c.c b/src/i2c.c index 2aa1130e..12bcec3a 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -15,6 +15,7 @@ #include #include #include +#include // I2C statuses #define I2C_READ_BIT ((uint8_t)0x01) @@ -38,16 +39,6 @@ typedef struct { volatile I2CStatus_TypeDef i2cState; -// _i2cDisableInt - Common I2C end routine to disable interrupts -static INLINE void _i2cDisableInt() { - I2C1->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); -} - -// _i2cEnableInt - Common I2C start routine to enable interrupts -static INLINE void _i2cEnableInt() { - I2C1->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN; -} - // I2C status flag initialization void _i2cInit() { Semaphore sync = semaphoreCreate(); @@ -59,26 +50,9 @@ void _i2cInit() { // _i2cRead - Reads the specified number of data bytes from the specified address static bool _i2cRead(uint8_t addr, uint8_t *data, uint16_t count) { volatile I2CStatus_TypeDef *state = &i2cState; - __disable_irq(); - { - // Set the I2C direction to reception, set LSB to receive properly - state->address = (addr << 1) | I2C_READ_BIT; - // Set up buffers - state->buffer = data; - state->count = count; - // Send START condition - I2C1->CR1 |= I2C_CR1_ACK | I2C_CR1_START; - state->status = 0; - } - __enable_irq(); - // Wait until START is reset (transmission begins) - do { - _taskYield(); - if (state->status & I2C_STATUS_ERR) - return false; - } while (!(I2C1->SR1 & I2C_SR1_SB)); - // Enable I2C interrupts - _i2cEnableInt(); + + EmuI2C_startRead(addr, (uint32_t)data, count); + do { // Wait until BUSY flag is reset (until a STOP is generated) semaphoreTake(i2cState.sync, 2); @@ -93,20 +67,9 @@ static bool _i2cRead(uint8_t addr, uint8_t *data, uint16_t count) { static bool _i2cWrite(uint8_t addr, uint8_t *data, uint16_t count) { uint8_t status; volatile I2CStatus_TypeDef *state = &i2cState; - __disable_irq(); - { - // Set the I2C direction to transmission, clear LSB to transmit properly - state->address = addr << 1; - // Set up buffers - state->buffer = data; - state->count = count; - // Send START condition - state->status &= ~(I2C_STATUS_ERR | I2C_STATUS_RESTART); - I2C1->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - } - __enable_irq(); - // Enable I2C interrupts - _i2cEnableInt(); + + EmuI2C_startWrite(addr, (uint32_t)data, count); + do { // Wait until BUSY flag is reset (until a STOP is generated) or repeated-start bit set semaphoreTake(i2cState.sync, 2); @@ -133,14 +96,9 @@ bool i2cReadRegister(uint8_t addr, uint8_t reg, uint8_t *value, uint16_t count) // i2cSetAddress - Sets the Cortex's I2C address void i2cSetAddress(uint8_t addr) { - uint16_t oar; // Limit to 7 bits addr &= 0xFE; - // Put it into OAR - oar = I2C1->OAR1; - oar &= ~0x00FE; - oar |= addr; - I2C1->OAR1 = oar; + EmuI2C_setAddr(addr); } // i2cWrite - Writes the specified number of data bytes to the specified address @@ -171,100 +129,15 @@ void _i2cEnd() { // I2C1 event interrupt void ISR_I2C1_EV() { - uint16_t sr1 = I2C1->SR1; volatile I2CStatus_TypeDef *state = &i2cState; - bool cs = false; - I2C1->SR2; - if (sr1 & I2C_SR1_SB) - // If SB = 1, START sent (EV5) - I2C1->DR = state->address; - else if (sr1 & I2C_SR1_ADDR) { - // If ADDR = 1, address sent (EV6) - uint8_t count = state->count; - // Write the first data when transmitting (LSB clear) - if (!(state->address & I2C_READ_BIT)) { - // Write the first data in the data register - I2C1->DR = *((state->buffer)++); - count--; - state->count = count; - // If no further data, disable buffer interrupt so as not to have a TXE interrupt - if (count == 0) - I2C1->CR2 &= ~I2C_CR2_ITBUFEN; - } else if (count == 1) { - // EV6_1, used for single byte reception. Disable ACK and program STOP - uint16_t cr = I2C1->CR1; - // No ACK, send STOP - cr = (cr & ~I2C_CR1_ACK) | I2C_CR1_STOP; - I2C1->CR1 = cr; - cs = true; - } - } else if (sr1 & I2C_SR1_TXE) { - uint8_t count = state->count; - // TXE set, transmit data - if (sr1 & I2C_SR1_BTF) { - uint8_t status = state->status; - // EV8_2, both BTF and TXE are set - if (status & I2C_STATUS_NOSTOP) - // Prepare for repeated START bit - state->status = (status & ~I2C_STATUS_NOSTOP) | I2C_STATUS_RESTART; - else - // Send STOP - I2C1->CR1 |= I2C_CR1_STOP; - // Disable event interrupt to avoid second BTF interrupt - _i2cDisableInt(); - cs = true; - } else if (count > 0) { - // Write data - I2C1->DR = *((state->buffer)++); - count--; - state->count = count; - // If no data left, avoid last TXE interrupt - if (count == 0) - I2C1->CR2 &= ~I2C_CR2_ITBUFEN; - } - } else if (sr1 & I2C_SR1_RXNE) { - uint8_t count = state->count; - // RXNE set, read in data - *((state->buffer)++) = I2C1->DR; - count--; - state->count = count; - // If one byte left, disable ACK and send STOP (EV7_1) - if (count == 1) - // No ACK, send STOP - I2C1->CR1 = (I2C1->CR1 & ~I2C_CR1_ACK) | I2C_CR1_STOP; - else if (count == 0) { - // All done - _i2cDisableInt(); - cs = true; - } - } - if (cs) - // One bit clock = 2.5us, add safety margin - _highResSchedule(2, 4); + state->count = 0; } // I2C1 error interrupt void ISR_I2C1_ER() { - uint16_t cr, flags = I2C1->SR1; bool cs = false; - // Store interrupt flags, then clear them - I2C1->SR1 = flags & ~(I2C_SR1_ARLO | I2C_SR1_BERR | I2C_SR1_OVR | I2C_SR1_AF); - cr = I2C1->CR1; - // Recover from arbitration lost and bus error via resetting I2C - if (flags & (I2C_SR1_ARLO | I2C_SR1_BERR | I2C_SR1_OVR)) { - // Software reset the I2C peripheral - I2C1->CR1 = cr | I2C_CR1_SWRST; - // This delay required for I2C to acknowledge the request - for (uint32_t delay = 0; delay < 32; delay++) asm volatile(""); - // Clear software reset - I2C1->CR1 = cr; - } else - // Send STOP bit - I2C1->CR1 = cr | I2C_CR1_STOP; - // Let SW know to break out of wait state i2cState.status |= I2C_STATUS_ERR; - // Disable future interrupts - _i2cDisableInt(); + semaphoreGiveISR(i2cState.sync, &cs); if (cs) _taskYield(); diff --git a/src/init.c b/src/init.c index 45468226..68d5033e 100644 --- a/src/init.c +++ b/src/init.c @@ -8,6 +8,7 @@ */ #include "main.h" +#include "emulator.h" /* * Runs pre-initialization code. This function will be started in kernel mode one time while the @@ -18,6 +19,7 @@ * configure a UART port (usartOpen()) but cannot set up an LCD (lcdInit()). */ void initializeIO() { + printf("initializeIO started\n"); } /* @@ -34,4 +36,5 @@ void initializeIO() { * can be implemented in this task if desired. */ void initialize() { + printf("initialize started\n"); } diff --git a/src/io.c b/src/io.c index 44ad2610..6cf986dd 100644 --- a/src/io.c +++ b/src/io.c @@ -18,155 +18,7 @@ // ADC data storage uint16_t adcDataIn[16]; -// Analog channel lookup table -const uint8_t _adcChannelTable[BOARD_NR_ADC_PINS] = { - // Ports go in order PA0 PA1 PA2 PA3 PC2 PC3 PC0 PC1 - 0, 1, 2, 3, 12, 13, 10, 11 -}; - -// I/O pin offset lookup table -const uint8_t _pinIndexTable[BOARD_NR_GPIO_PINS] = { - // 12 Digital pins and the SP output - 4, 9, 11, 6, 7, 13, 14, 8, 10, 12, 7, 0, 1, - // 8 Analog pins - 0, 1, 2, 3, 2, 3, 0, 1, - // 6 Communications pins - 5, 6, 10, 11, 8, 9 -}; - -// I/O pin register lookup table -const GPIO_TypeDef* const _pinLookupTable[BOARD_NR_GPIO_PINS] = { - // 12 Digital pins and the SP output - GPIOA, GPIOE, GPIOE, GPIOC, GPIOC, GPIOE, GPIOE, GPIOE, GPIOE, GPIOE, GPIOE, GPIOD, GPIOD, - // 8 Analog pins - GPIOA, GPIOA, GPIOA, GPIOA, GPIOC, GPIOC, GPIOC, GPIOC, - // 6 Communications pins - GPIOD, GPIOD, GPIOC, GPIOC, GPIOB, GPIOB -}; - -// _ioConfigure - Internal routine to configure the CRL/CRH registers -static void _ioConfigure(__IO uint32_t *CR, uint8_t index, uint8_t bits) { - uint32_t value; - // Index goes up by 4 for every pin, so multiply by 4 - index <<= 2; - // Mask off original value - value = *CR; - value &= ~(((uint32_t)0xF) << index); - // Move in new value - value |= ((uint32_t)bits) << index; - *CR = value; -} - -// adcOff - Stops the ADC, use before reconfiguring -void adcOff() { - _enterCritical(); - { - ADC1->CR2 &= ~ADC_CR2_ADON; - DMA1_Channel1->CCR &= ~DMA_CCR_EN; - } - _exitCritical(); -} - -// adcOn - Starts the ADC -void adcOn() { - _enterCritical(); - { - uint32_t temp = ADC1->CR2; - if (!(temp & ADC_CR2_ADON)) - temp |= ADC_CR2_ADON; - DMA1_Channel1->CCR |= DMA_CCR_EN; - ADC1->CR2 = temp | ADC_CR2_SWSTART; - } - _exitCritical(); -} - // adcRead - Reads a channel 0-15 from the ADC uint16_t adcRead(uint32_t channel) { return adcDataIn[channel & (uint32_t)0xF]; } - -// adcSetChannels - Sets the channels sampled by the ADC (ADC must be off!) -void adcSetChannels(uint32_t num, ...) { - uint32_t i, offset = 0; - va_list args; - if (num && num <= 16) { - _enterCritical(); - { - // Store count - uint32_t sqr[3], *ptr = &sqr[2]; - sqr[0] = (num - 1) << 20; - sqr[1] = 0; - sqr[2] = 0; - DMA1_Channel1->CNDTR = num; - va_start(args, num); - for (i = 0; i < num; i++) { - // Store in 5-bit positions - *ptr |= ((uint32_t)(va_arg(args, int)) & 0x1F) << offset; - offset += 5; - if (offset >= 30) { - // Move up a register - ptr--; - offset = 0; - } - } - va_end(args); - ADC1->SQR1 = sqr[0]; - ADC1->SQR2 = sqr[1]; - ADC1->SQR3 = sqr[2]; - } - _exitCritical(); - } -} - -// ioMultiSetDirection - Configures the specified pins in the bit mask to the given type -void ioMultiSetDirection(GPIO_TypeDef* port, uint16_t pinMask, uint32_t type) { - uint32_t i, mod; - type &= 0x0F; - mod = type & 0x0D; - _enterCritical(); - { - for (i = 0; i < 8; i++) { - // Look for pins to configure - if (pinMask & 1) { - _ioConfigure(&(port->CRL), i, mod); - // Set the pullup/pulldown depending on the twos bit - if (mod == DDR_INPUT_PULLDOWN) - ioSetOutput(port, i, type & 0x02); - } - pinMask >>= 1; - } - for (i = 0; i < 8; i++) { - // Look for pins to configure - if (pinMask & 1) { - _ioConfigure(&(port->CRH), i, mod); - // Set the pullup/pulldown depending on the twos bit - if (mod == DDR_INPUT_PULLDOWN) - ioSetOutput(port, i + 8, type & 0x02); - } - pinMask >>= 1; - } - } - _exitCritical(); -} - -// ioSetDirection - Configures the pin as an input or output with a variety of settings -void ioSetDirection(GPIO_TypeDef* port, uint32_t pin, uint32_t type) { - uint32_t mod; - _enterCritical(); - { - // Force pin in range - pin &= 0x0F; - type &= 0x0F; - mod = type & 0x0D; - if (pin > 7) - // High bits - _ioConfigure(&(port->CRH), pin - 8, mod); - else - // Low bits - _ioConfigure(&(port->CRL), pin, mod); - // Set the pullup/pulldown depending on the twos bit - if (mod == DDR_INPUT_PULLDOWN) - ioSetOutput(port, pin, type & 0x02); - } - _exitCritical(); -} diff --git a/src/kernel.c b/src/kernel.c index dad96548..0eb66e7a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -20,6 +20,7 @@ #include #include #include +#include // Low-resolution clock extern volatile uint32_t _clockLowRes; @@ -27,37 +28,76 @@ extern volatile uint32_t _clockLowRes; // libc init functions //extern void __libc_init_array(); +static const char * const hex = "0123456789ABCDEF"; +static void _fault_dumpInt(const char* prefix, uint32_t num) { + while (*prefix != 0) EmuSerial_putc(1, *prefix++); + EmuSerial_putc(1, '0'); + EmuSerial_putc(1, 'x'); + unsigned char i = 32; + while (i) { + i -= 4; + EmuSerial_putc(1, hex[(num >> i) % 16]); + } + EmuSerial_putc(1, '\r'); + EmuSerial_putc(1, '\n'); +} + // Error messages for _exit // Since SDIV by 0 is configured not to fault, no divide by 0 can occur here static const char * const errorMessages[] = { "Segmentation fault\n", "Segmentation fault\n", "Illegal instruction\n", "Stack overflow\n", "System task failure\n" }; + static const char * const crashMessage = "\r\nThe VEX Cortex has stopped working!\r\nError cause: "; -// _exit - Exits the program with an error message -void __attribute__((noreturn)) _exit(int status) { - char c; char const * buffer = crashMessage; - __disable_irq(); - // No point in safeRobot(), since no interrupts can run and therefore no - // EXTI or SPI interrupts can be used to send state/start user code - USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; - // Dump it out over debug USART manually - while ((c = *buffer++) != 0) { - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = c; - } - // Dump message - if ((unsigned int)status < 5U) { - buffer = errorMessages[status]; +uint32_t _fault_dumpPC(int status, volatile uint32_t *faultStack) { + __disable_irq(); + _fault_dumpInt("r0 = ", faultStack[0]); + _fault_dumpInt("r1 = ", faultStack[1]); + _fault_dumpInt("r2 = ", faultStack[2]); + _fault_dumpInt("r3 = ", faultStack[3]); + _fault_dumpInt("r12 = ", faultStack[4]); + _fault_dumpInt("lr = ", faultStack[5]); + _fault_dumpInt("pc = ", faultStack[6]); + _fault_dumpInt("psr = ", faultStack[7]); + + char c; char const * buffer = crashMessage; + + // Dump it out over debug USART manually while ((c = *buffer++) != 0) { - while (!(USART1->SR & USART_SR_TXE)); - USART1->DR = c; + EmuSerial_putc(1, c); + } + // Dump message + if ((unsigned int)status < 5U) { + buffer = errorMessages[status]; + while ((c = *buffer++) != 0) + EmuSerial_putc(1, c); } - } - // Wait for last character - while (!(USART1->SR & USART_SR_TXE)); + + __reset(); +} + +// some ASM that calls our _fault_dumpPC function with a pointer to the stack that caused the fault +static void _fault_test(int status) __attribute__( ( naked ) ); +static void _fault_test(int status) { + __asm volatile ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r1, msp \n" + " mrsne r1, psp \n" + " ldr r2, [r1, #24] \n" + " ldr r3, handler2_address_const \n" + " bx r3 \n" + " handler2_address_const: .word _fault_dumpPC \n" + ); +} + +// _exit - Exits the program with an error message +void __attribute__((noreturn)) _exit(int status) { + _fault_test(status); + // Reset CPU __reset(); } @@ -84,8 +124,6 @@ IRQ ISR_UsageFault() { // ISR_SysTick - Interrupt service routine for the SysTick interrupt IRQ ISR_SysTick() { _clockLowRes++; - if (_clockLowRes % 20 == 0) - svStartTransfer(); _taskTick(); } diff --git a/src/motorcontrol.c b/src/motorcontrol.c index bde9cf2a..665cc10b 100644 --- a/src/motorcontrol.c +++ b/src/motorcontrol.c @@ -21,161 +21,17 @@ #define MOTOR_FLAG_1 1 #define MOTOR_FLAG_10 2 -// Motor #1 and #10 control values -static volatile uint8_t motor1, motor10; -// Motor flag bits for consolidating the motor application calls -static volatile uint16_t motorFlags; - -// _motorApply1 - Set PWM value for motor port #1 -static void _motorApply1() { - uint8_t value = motor1; - // PWM values 126 and 128 do not give any meaningful motor impulse - if (value > 128) { - // Forward - TIM4->CCR1 = (uint16_t)0; - ioSetOutput(GPIOD, 4, 0); - ioSetOutput(GPIOD, 3, 1); - TIM4->CCR2 = (uint16_t)(value - 128); - } else if (value <= 126) { - // Reverse - TIM4->CCR2 = (uint16_t)0; - ioSetOutput(GPIOD, 3, 0); - ioSetOutput(GPIOD, 4, 1); - TIM4->CCR1 = (uint16_t)(127 - value); - } else { - // Stop - clear GPIOD 3 and 4 - TIM4->CCR1 = (uint16_t)0; - TIM4->CCR2 = (uint16_t)0; - GPIOD->BRR = 0x0018; - } - TIM4->CCMR1 = (uint16_t)0x6868; -} - -// _motorApply10 - Set PWM value for motor port #10 -static void _motorApply10() { - uint8_t value = motor10; - // PWM values 126 and 128 do not give any meaningful motor impulse - if (value > 128) { - // Forward - TIM4->CCR3 = (uint16_t)0; - ioSetOutput(GPIOD, 8, 0); - ioSetOutput(GPIOD, 7, 1); - TIM4->CCR4 = (uint16_t)(value - 128); - } else if (value <= 126) { - // Reverse - TIM4->CCR4 = (uint16_t)0; - ioSetOutput(GPIOD, 7, 0); - ioSetOutput(GPIOD, 8, 1); - TIM4->CCR3 = (uint16_t)(127 - value); - } else { - // Stop - clear GPIOD 7 and 8 - TIM4->CCR3 = (uint16_t)0; - TIM4->CCR4 = (uint16_t)0; - GPIOD->BRR = 0x0180; - } - TIM4->CCMR2 = (uint16_t)0x6868; -} - -// _motorApply - Apply PWM values for motors as needed -void _motorApply() { - uint16_t flags = motorFlags; - if (flags & MOTOR_FLAG_1) - // If motor 1 needs applying, apply it - _motorApply1(); - if (flags & MOTOR_FLAG_10) - // If motor 10 needs applying, apply it - _motorApply10(); - // Reset all flags - motorFlags = 0; -} - // motorControlGet - Gets the last sent PWM value of a channel 1..10 from 0 to 255 uint8_t motorControlGet(uint32_t channel) { - // Map the channel from 1..10 to 0..9 - channel--; - if (channel == 0) - return motor1; - else if (channel == 9) - return motor10; - else if (channel < 9) - return svGetOutputData(channel - 1); - return 0; -} - -// Set the PWM value of channel 1 from 0 to 255 -static INLINE void motorControlSet1(uint8_t value) { - _enterCritical(); - { - uint8_t oldMotor = motor1; - uint16_t flag = motorFlags & MOTOR_FLAG_1; - motor1 = value; - if (!flag) { - if ((value > 127 && oldMotor < 127) || (value < 127 && oldMotor > 127)) { - TIM4->CCR1 = (uint16_t)0; - TIM4->CCR2 = (uint16_t)0; - GPIOD->BRR = 0x0018; - TIM4->CCMR1 = (uint16_t)0x4848; - _highResSchedule(1, 360); - motorFlags |= MOTOR_FLAG_1; - } else - // Avoid rapid flip-flops from racing to _motorApply1() - _motorApply1(); - } - } - _exitCritical(); -} - -// Set the PWM value of channel 10 from 0 to 255 -static INLINE void motorControlSet10(uint8_t value) { - _enterCritical(); - { - uint8_t oldMotor = motor10; - uint16_t flag = motorFlags & MOTOR_FLAG_10; - motor10 = value; - if (!flag) { - if ((value > 127 && oldMotor < 127) || (value < 127 && oldMotor > 127)) { - TIM4->CCR3 = (uint16_t)0; - TIM4->CCR4 = (uint16_t)0; - GPIOD->BRR = 0x0180; - TIM4->CCMR2 = (uint16_t)0x4848; - _highResSchedule(1, 360); - motorFlags |= MOTOR_FLAG_10; - } else - // Avoid rapid flip-flops from racing to _motorApply10() - _motorApply10(); - } - } - _exitCritical(); + return EmuMotor_get(channel - 1); } // motorControlSet - Sets the PWM value of a channel 1..10 from 0 to 255 void motorControlSet(uint32_t channel, uint8_t value) { - // Map the channel from 1..10 to 0..9 - channel--; - if (channel == 0) - motorControlSet1(value); - else if (channel == 9) - motorControlSet10(value); - else if (channel < 9) - svSetData(channel - 1, value); + EmuMotor_set(channel - 1, value); } // motorControlStop - Stops all motors void motorControlStop() { - _enterCritical(); - { - // Clear the following pins: PD3, PD4, PD7, PD8 - GPIOD->BRR = 0x0198; - // Reset TIM4's CCRs to zero - TIM4->CCR1 = (uint16_t)0; - TIM4->CCR2 = (uint16_t)0; - TIM4->CCR3 = (uint16_t)0; - TIM4->CCR4 = (uint16_t)0; - // Reset motor values - motor1 = motor10 = 127; - motorFlags = 0; - // Load neutral into all supervisor data values - svSetAllData(127); - } - _exitCritical(); + EmuMotor_stop(); } diff --git a/src/opcontrol.c b/src/opcontrol.c index a67119ce..f20c4899 100644 --- a/src/opcontrol.c +++ b/src/opcontrol.c @@ -8,6 +8,7 @@ */ #include "main.h" +#include /* * Runs the user operator control code. This function will be started in its own task with the @@ -27,8 +28,7 @@ * This task should never exit; it should end with some kind of infinite loop, even if empty. */ void operatorControl() { - while (1) { - printf("Hello PROS User!\n"); - delay(20); - } + printf("operatorControl started\n"); + //delay(5000); + //((void(*)())0x69696969)(); } diff --git a/src/supervisor.c b/src/supervisor.c index a3a53ac2..5d9bb466 100644 --- a/src/supervisor.c +++ b/src/supervisor.c @@ -30,7 +30,7 @@ #endif // Buffers for SPI communications (16 words = 32 bytes) -volatile uint16_t spiBufferRX[16], spiBufferTX[16]; +volatile uint16_t spiBufferRX[16]; // Flag bits for the FMS volatile uint16_t svFlags; // Last flag bits for the FMS @@ -44,126 +44,25 @@ static uint8_t svPacket; // Team name to report when asked for configuration char svTeamName[8]; -// Supervisor transfer complete, check the flags sent -static INLINE void _svComplete() { - uint8_t temp, i; uint16_t flags = 0; - // Start checking the configuration bits - if (SV_IN->key == SV_MAGIC) { - temp = SV_IN->inMode; - if (temp & 2) { - // Configuration (team name?) - if (temp & 1) { - // Default data - SV_OUT->mode = 3; - SV_OUT->outMode = 0; - svSetAllData(127); - } else { - // Team name - SV_OUT->mode = 2; - SV_OUT->outMode = 85; - for (i = 0; i < 8; i++) - SV_OUT->data[i] = svTeamName[i]; - } - } else if (temp & 4) - // Ready for mode set - SV_OUT->mode = 8; - else if (temp == 8) { - // Mode set - SV_OUT->mode = 8; - flags = SV_CONNECTED; - // Check the game state - temp = SV_IN->gameStatus; - if (temp & (uint8_t)0x08) { - // FMS is connected - flags |= SV_FMS; - if (temp & (uint8_t)0x40) - // Autonomous mode - flags |= SV_AUTONOMOUS; - if (!(temp & (uint8_t)0x80)) - // Enabled - flags |= SV_ENABLED; - } - if (flags != svLastFlags) { - // Something changed! Wake up the daemon to take action - svLastFlags = flags; - invWakeup(); - } - // Backup battery fix - if (SV_IN->mainBattery <= 32) { - if (svPowerFlags < 64) svPowerFlags++; - } else { - if (svPowerFlags > 0) svPowerFlags--; - } - } - // Update the supervisor flags - svFlags = flags; - } -} - -// _spiDoNext - Reads an SPI byte and inserts delay if needed -static void _spiDoNext() { - uint8_t idx = svIndex; - // Receive buffer full, read data - spiBufferRX[idx++] = SPI1->DR; - svIndex = idx; - // Negate NSS - ioSetOutput(GPIOE, 0, 1); - if (idx < 16) { - if (idx & 3) { - // Setup/hold time of 8? us - _highResSchedule(0, 8); - } else { - // Setup/hold time of 73? us - _highResSchedule(0, 73); - } - } else { - // All done - _svComplete(); - svIndex = 0; - } -} - -// _svNextByte - Helper to send off the next byte for SPI -void _svNextByte() { - uint8_t idx = svIndex; - if (idx == 4) - ioSetOutput(GPIOA, 11, 0); - // Assert SS (GPIOE 0) and store next value - ioSetOutput(GPIOE, 0, 0); - SPI1->DR = spiBufferTX[idx]; -} - // standaloneModeEnable - enable standalone operation void standaloneModeEnable() { // set flag in outgoing SPI buffer to enable standlone mode - SV_OUT->flags |= 1; + EmuComp_enableStandalone(); } // svInit - Initialize supervisor communications void svInit() { + EmuComp_init(); + uint8_t i; - // Wait for the supervisor to come up - ioSetOutput(GPIOE, 0, 1); + svPacket = (uint8_t)0x00; - // Read 8 bytes of garbage data (?) - for (i = 8; i; i--) - (void)SPI1->DR; - // When the requisite port E pins [3 and 4] go low, master is ready for SPI data - while (ioGetInput(GPIOE, 3) || ioGetInput(GPIOE, 4)) __sleep(); // Reset all flags svFlags = (uint32_t)0x00000000; svLastFlags = (uint32_t)0x00000000; svPowerFlags = (uint16_t)0x0000; svIndex = (uint8_t)0x00; - // Initialize the array - for (i = 1; i < 16; i++) - spiBufferTX[i] = (uint16_t)0x0000; - SV_OUT->key = SV_MAGIC; - SV_OUT->mode = 2; - SV_OUT->flags = 0; - SV_OUT->version = 1; - // Load in empty motor values - svSetAllData((uint8_t)0x7F); + // Load in neutral joystick values for (i = 0; i < 6; i++) { SV_IN->joystick[0].axis[i] = (uint8_t)0x7F; @@ -183,8 +82,6 @@ void svInit() { svTeamName[5] = ' '; svTeamName[6] = ' '; svTeamName[7] = ' '; - // Now we are ready to enable RXNE interrupt - SPI1->CR2 = SPI_CR2_RXNEIE; } // svSynchronize - Waits for the supervisor to synchronize, then prints the startup message @@ -200,26 +97,37 @@ void svSynchronize() { // ISR_SPI1 - Interrupt-driven routine to handle master communication void ISR_SPI1() { - if (SPI1->SR & SPI_SR_RXNE) - _spiDoNext(); -} + if (EMULATOR->R1 == 0) { + svFlags |= SV_CONNECTED; + } else if (EMULATOR->R1 == 1) { + uint8_t temp; uint16_t flags = 0; + EmuComp_setName(svTeamName); + EmuComp_getStatus((void*)spiBufferRX); -// Updates the SPI master on each tick -void svStartTransfer() { - // Check power level to fix backup battery issues - if (svPowerFlags > 32) - svSetAllData((uint8_t)0x7F); - if (svIndex == 0) { - // Packet number goes in the last byte (assuming that overflow is fine here) - SV_OUT->packetNum = svPacket++; - if (SPI1->SR & SPI_SR_TXE) { - // Raise GPIOA 11 high - ioSetOutput(GPIOA, 11, 1); - // Assert SS - ioSetOutput(GPIOE, 0, 0); - // Start by storing first data value - SPI1->DR = spiBufferTX[0]; + temp = SV_IN->gameStatus; + if (temp & (uint8_t)0x08) { + // FMS is connected + flags |= SV_FMS; + if (temp & (uint8_t)0x40) + // Autonomous mode + flags |= SV_AUTONOMOUS; + if (!(temp & (uint8_t)0x80)) + // Enabled + flags |= SV_ENABLED; + } + if (flags != svLastFlags) { + // Something changed! Wake up the daemon to take action + svLastFlags = flags; + invWakeup(); } - } else - _spiDoNext(); + + // Backup battery fix + if (SV_IN->mainBattery <= 32) { + if (svPowerFlags < 64) svPowerFlags++; + } else { + if (svPowerFlags > 0) svPowerFlags--; + } + + svFlags = flags; + } } diff --git a/src/system.c b/src/system.c index a1a08878..b6c1a11e 100644 --- a/src/system.c +++ b/src/system.c @@ -16,20 +16,11 @@ #include #include #include +#include // Low-resolution clock volatile uint32_t _clockLowRes; -// Prototype this from motorcontrol.c -void _motorApply(); - -// Prototype these from i2c.c -void _i2cEnd(); -void _i2cInit(); - -// Prototype this from supervisor.c -void _svNextByte(); - // Prototype this from ultrasonic.c void _ultrasonicTimeout(); @@ -56,40 +47,6 @@ static INLINE void intSetPriority(IRQn_Type irq, uint32_t priority) { NVIC->IP[(uint32_t)irq] = (priority << 4) & 0xFF; } -// initADC - Initializes the analog converter on the 8 analog sensor pins -static INLINE void initADC() { - uint32_t temp; - // Turn the ADC clock on - RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; - // Reset ADC - temp = RCC->APB2RSTR; - RCC->APB2RSTR = temp | RCC_APB2RSTR_ADC1RST; - __dsb(); - // Clear reset - RCC->APB2RSTR = temp; - // Independent ADC, scan mode - ADC1->CR1 = ADC_CR1_SCAN; - // No external trigger, right-aligned, continuous conversions - temp = ADC_CR2_NOTRIG | ADC_CR2_CONT | ADC_CR2_DMA; - ADC1->CR2 = temp; - // 8 channels, sampling order 0 1 2 3 12 13 10 11 - adcSetChannels(8, 0, 1, 2, 3, 12, 13, 10, 11); - // Set all channels' sampling time to 55.5 cycles - ADC1->SMPR1 = (uint32_t)0x00B6DB6D; - ADC1->SMPR2 = (uint32_t)0x2DB6DB6D; - // ADC on - temp |= ADC_CR2_ADON; - ADC1->CR2 = temp; - // Reset calibration - ADC1->CR2 = temp | ADC_CR2_RSTCAL; - while (ADC1->CR2 & ADC_CR2_RSTCAL); - // Begin calibration - ADC1->CR2 = temp | ADC_CR2_CAL; - while (ADC1->CR2 & ADC_CR2_CAL); - // Start eternal conversion - adcOn(); -} - // initClocks - Starts the MCU clocks at the intended speed (72 MHz) // No startup timeout is enforced since the entire Cortex will come crashing down if the clocks // cannot get to the correct speed; might as well hang. In the future, a "clock monitor fail" @@ -108,11 +65,7 @@ static INLINE void initClocks() { RCC->CFGR &= ~RCC_CFGR_SW; // Wait for HSE to start up while (!(RCC->CR & RCC_CR_HSERDY)); - temp = FLASH->ACR; - temp &= ~FLASH_ACR_LATENCY; - // Prefetch buffer on, 2 wait states (reason for the prefetch buffer) - temp |= FLASH_ACR_LATENCY_2 | FLASH_ACR_PRFTBE; - FLASH->ACR = temp; + // APB1 is 36 MHz and APB2 is 72 MHz // ADC clock is 12 MHz (72 MHz / 6) // PLL enabled from HSE = 8 MHz * 9 = 72 MHz @@ -130,42 +83,6 @@ static INLINE void initClocks() { _clockLowRes = 0; } -// initDAC - Initializes DAC to run the Wave driver -static INLINE void initDAC() { - uint32_t temp; - // Turn the DAC clock on - RCC->APB1ENR |= RCC_APB1ENR_DACEN; - // Reset DAC - temp = RCC->APB1RSTR; - RCC->APB1RSTR = temp | RCC_APB1RSTR_DACRST; - __dsb(); - // Clear reset - RCC->APB1RSTR = temp; - // Turn on DAC channel 1 and auto-connect output (in analog mode) PA4, pull from TIM6 - // (default), enable trigger and DMA - DAC->CR = DAC_CR_DMAEN1 | DAC_CR_EN1 | DAC_CR_BOFF1 | DAC_CR_TEN1; -} - -// initDMA - Initializes DMA1 for the ADC and Maple -static INLINE void initDMA() { - // Turn the DMA1 clock on - RCC->AHBENR |= RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN; - // Transfer from ADC1's DR to the adcDataIn array with a buffer size of 8, no peripheral - // address increment, memory address increment, 16 bits at a time, circular mode, - // default priority - DMA1_Channel1->CCR = DMA_CCR_SRC | DMA_CCR_MEMINC | DMA_CCR_SRC_HWORD | DMA_CCR_DST_HWORD | - DMA_CCR_CIRC | DMA_CCR_PRI_HIGH; - DMA1_Channel1->CPAR = (uint32_t)(&(ADC1->DR)); - DMA1_Channel1->CMAR = (uint32_t)(&adcDataIn); - // Transfer from the wave array to DAC1's DR with a buffer size of ?, no peripheral - // address increment, memory address increment, 16 bits at a time, circular mode, default - // priority - DMA2_Channel3->CCR = DMA_CCR_DST | DMA_CCR_MEMINC | DMA_CCR_SRC_HWORD | DMA_CCR_DST_HWORD | - DMA_CCR_CIRC | DMA_CCR_PRI_HIGH | DMA_CCR_TCIE | DMA_CCR_HTIE; - DMA2_Channel3->CPAR = (uint32_t)(&(DAC->DHR12R1)); - // DMA turned on in the ADC/DAC call -} - // initEXTI - Initializes the external interrupts static INLINE void initEXTI() { // Mask all interrupts and events @@ -186,39 +103,6 @@ static INLINE void initEXTI() { EXTI->PR = (uint32_t)0x0007FFFF; } -// initI2C - Initializes the I2C port -static INLINE void initI2C() { - uint32_t temp; - // Initialize I2C flags - _i2cInit(); - // Turn the I2C clock on - RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; - // Reset I2C - temp = RCC->APB1RSTR; - RCC->APB1RSTR = temp | RCC_APB1RSTR_I2C1RST; - __dsb(); - // Clear reset - RCC->APB1RSTR = temp; - // OFF to configure - I2C1->CR1 = I2C_CR1_SWRST; - // This delay required for I2C to acknowledge the request - for (uint32_t delay = 0; delay < 32; delay++) asm volatile(""); - I2C1->CR1 = 0; - // Set peripheral clock frequency to 36 MHz - I2C1->CR2 = (uint16_t)36 | I2C_CR2_ITERREN; - // Set I2C clock to 400 KHz (Standard mode) - I2C1->CCR = I2C_CCR_FS | ((uint16_t)90); - I2C1->TRISE = ((uint16_t)10); - // No reset, no error checking, no general call response, disable SMBus mode - I2C1->CR1 |= I2C_CR1_PE | I2C_CR1_ACK; - // Single-address mode - i2cSetAddress(I2C_OWN_ADDR); - I2C1->OAR2 &= ~I2C_OAR2_ENDUAL; - // Set up GPIOB 8 and 9 [I2C SCL, I2C SDA] as alternate function outputs open-drain - ioSetDirection(PIN_I2C1_SCL, DDR_AFO_OD); - ioSetDirection(PIN_I2C1_SDA, DDR_AFO_OD); -} - // initInterrupts - Initializes the NVIC (interrupt system) static INLINE void initInterrupts() { // Vector table is at start of Flash @@ -296,48 +180,34 @@ static INLINE void initPorts() { __dsb(); // Clear reset RCC->APB2RSTR = temp; - // Set up GPIOA 0..4 [Analog 1, 2, 3, 4, SP] as analog inputs - ioMultiSetDirection(GPIOA, 0x001F, DDR_INPUT_ANALOG); - // Set up GPIOA 5, 7 [SPI1 MOSI, SCK] and 9 as alternate function outputs push-pull - ioMultiSetDirection(GPIOA, 0x02A0, DDR_AFO); - // Set up GPIOA 10 as a floating input - ioSetDirection(GPIOA, 10, DDR_INPUT_FLOATING); - // Set up GPIOA 11 as a push-pull output - ioSetDirection(GPIOA, 11, DDR_OUTPUT); - // All remaining GPIOA pins to pull-up inputs (power consumption) - ioMultiSetDirection(GPIOA, 0xF140, DDR_INPUT_PULLUP); + + EmuGPIO_SetDir(PIN_ANALOG_1, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_2, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_3, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_4, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_5, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_6, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_7, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_8, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_ANALOG_9, DDR_INPUT_ANALOG); + // Turn on GPIOB 8 & 9 [I2C SCL, SDA] pre-emptively - ioSetDirection(PIN_I2C1_SCL, DDR_OUTPUT); - ioSetDirection(PIN_I2C1_SDA, DDR_OUTPUT); - ioSetOutput(PIN_I2C1_SCL, 1); - ioSetOutput(PIN_I2C1_SDA, 1); - // All remaining GPIOB pins to pull-up inputs (power consumption) - ioMultiSetDirection(GPIOB, 0xFCFF, DDR_INPUT_PULLUP); - // Set up GPIOC 0..3 [Analog 7, 8, 5, 6] as analog inputs - ioMultiSetDirection(GPIOC, 0x000F, DDR_INPUT_ANALOG); + EmuGPIO_SetDir(PIN_I2C1_SCL, DDR_OUTPUT); + EmuGPIO_SetDir(PIN_I2C1_SDA, DDR_OUTPUT); + EmuGPIO_SetOutput(PIN_I2C1_SCL, 1); + EmuGPIO_SetOutput(PIN_I2C1_SDA, 1); + // Set up GPIOC 10 [UART2 TX] as an alternate function output push-pull - ioSetDirection(PIN_UART2_TX, DDR_AFO); + EmuGPIO_SetDir(PIN_UART2_TX, DDR_AFO); // Set up GPIOC 11 [UART2 RX] as a floating input - ioSetDirection(PIN_UART2_RX, DDR_INPUT_FLOATING); - // Set up GPIOC 13..15 as input pull-down - ioMultiSetDirection(GPIOC, 0xE000, DDR_INPUT_PULLDOWN); - // All remaining GPIOC pins to pull-up inputs (power consumption) - ioMultiSetDirection(GPIOC, 0x13F0, DDR_INPUT_PULLUP); + EmuGPIO_SetDir(PIN_UART2_RX, DDR_INPUT_FLOATING); + motorControlStop(); // Set up GPIOD 5 [UART1 TX] as an alternate function output push-pull - ioSetDirection(PIN_UART1_TX, DDR_AFO); + EmuGPIO_SetDir(PIN_UART1_TX, DDR_AFO); // Set up GPIOD 6 [UART1 RX] as a floating input - ioSetDirection(PIN_UART1_RX, DDR_INPUT_FLOATING); - // Set up GPIOD 3, 4, 7, and 8 as push-pull outputs - ioMultiSetDirection(GPIOD, 0x0198, DDR_OUTPUT); - // Set up GPIOD 12..15 [TIM4 CH1-4] as alternate function outputs push-pull - ioMultiSetDirection(GPIOD, 0xF000, DDR_AFO); - // All remaining GPIOD pins to pull-up inputs (power consumption) - ioMultiSetDirection(GPIOD, 0x0E07, DDR_INPUT_PULLUP); - // Set up GPIOE 0, 5, and 6 [SPI handshake?] as push-pull outputs - ioMultiSetDirection(GPIOE, 0x0061, DDR_OUTPUT); - // All remaining GPIOE pins [including GPIOE 3..4] to pull-up inputs (power consumption) - ioMultiSetDirection(GPIOE, 0xFF9E, DDR_INPUT_PULLUP); + EmuGPIO_SetDir(PIN_UART1_RX, DDR_INPUT_FLOATING); + // Remap the following: USART2, USART3, TIM4, I2C1, TIM1 AFIO->MAPR = AFIO_MAPR_TIM4_REMAP | AFIO_MAPR_USART2_REMAP | AFIO_MAPR_USART3_REMAP | AFIO_MAPR_I2C1_REMAP | AFIO_MAPR_TIM1_REMAP_FULL; @@ -347,53 +217,10 @@ static INLINE void initPorts() { // initSerial - Sets up the USARTs for communication through the UART ports and debug terminal static INLINE void initSerial() { - uint32_t temp; // Ready the buffers usartBufferInit(); - // Turn on USART 1, 2 and 3 clocks - RCC->APB2ENR |= RCC_APB2ENR_USART1EN; - RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_USART3EN; - // Reset USART1 - temp = RCC->APB2RSTR; - RCC->APB2RSTR = temp | RCC_APB2RSTR_USART1RST; - __dsb(); - // Clear reset - RCC->APB2RSTR = temp; - // Reset USART2 and USART3 - temp = RCC->APB1RSTR; - RCC->APB1RSTR = temp | (RCC_APB1RSTR_USART2RST | RCC_APB1RSTR_USART3RST); - __dsb(); - // Clear reset - RCC->APB1RSTR = temp; - // Default: 8 data bits, no parity, no flow control, one stop bit - USART2->CR1 = (uint16_t)0; - USART3->CR1 = (uint16_t)0; - // 115200 baud on the fast bus = 625, on the slow bus = 308 - // But they want a weird 230113 baud = 313... - USART1->BRR = (uint16_t)313; - // Turn on USART1 - USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; -} -// initSPI - Sets up SPI1 for communication to the master -static INLINE void initSPI() { - uint32_t temp; - // Turn on SPI clock - RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; - // Reset the SPI - temp = RCC->APB2RSTR; - RCC->APB2RSTR = temp | RCC_APB2RSTR_SPI1RST; - __dsb(); - // Clear reset - RCC->APB2RSTR = temp; - // CPOL = 0, CPHA = 1, Master mode, 16-bit data size, Software NSS, divide by 32, MSB first - SPI1->CR1 = SPI_CR1_CPHA_1 | SPI_CR1_MSTR | SPI_CR1_16BIT | SPI_CR1_DIV32 | SPI_CR1_SPE | - SPI_CR1_NSS_SOFT; - // Do not enable the RXNE interrupt here as supervisor is not ready yet - // If the interrupt is turned on too soon, it will get serviced the moment that - // initInterrupts() calls "cpsie i", which sends garbage to the supervisor and gets a - // red code error light. - SPI1->CR2 = 0; + EmuSerial_init(1, 230113, 0); } // initTimers - Initializes the TIM modules for the desired interrupt frequencies @@ -471,14 +298,10 @@ void initMCU() { initClocks(); initPorts(); initEXTI(); - initSPI(); initSerial(); - initI2C(); initTimers(); - initDMA(); - initADC(); - initDAC(); initInterrupts(); + EmuGPIO_ADCInit((uint32_t)adcDataIn); } // ISR_TIM8_CC - Timer 8 capture/compare (microsecond queue) @@ -487,20 +310,14 @@ void ISR_TIM8_CC() { if (sr & TIM_SR_CC1IF) { // CC1 fired one-time TIM8->DIER &= ~TIM_DIER_CC1IE; - // Supervisor - _svNextByte(); } if (sr & TIM_SR_CC2IF) { // CC2 fired one-time TIM8->DIER &= ~TIM_DIER_CC2IE; - // Apply motors - _motorApply(); } if (sr & TIM_SR_CC3IF) { // CC3 fired one-time TIM8->DIER &= ~TIM_DIER_CC3IE; - // I2C timing event - _i2cEnd(); } if (sr & TIM_SR_CC4IF) // CC4 fired one-time, special handling due to recursive scheduling diff --git a/src/watchdog.c b/src/watchdog.c index 6308a659..0c3c695d 100644 --- a/src/watchdog.c +++ b/src/watchdog.c @@ -16,38 +16,5 @@ #include #include -static bool iwdgEnabled = false; - -// iwdgInit - Enables the watchdog -void watchdogInit() { - iwdgEnabled = true; -} - -// iwdgFeed - Resets the watchdog's timer -static inline void _iwdgFeed() { - IWDG->KR = 0xAAAA; -} - -static void _iwdgTask(void* ud) { - (void)(ud); - clock_t now = timeLowRes(); - for (;;) { - _iwdgFeed(); - taskDelayUntil(&now, 125); - } -} - -// iwdgStart - Initializes the watchdog with a timeout -void watchdogStart() { - // implementation based on STM32 IWDG guidance. (https://goo.gl/sQaIF3) - if (!iwdgEnabled) return; - - IWDG->KR = 0x5555; // enable access to iwdg reg (prevents accidental writes into iwdg cofig by runaway code) - IWDG->PR = 2; // prescaler divides low speed internal (LSI) oscillator - IWDG->RLR = 2500; // (timeout * 40) / exp(2, (2 + prescalerCode)) as per specification - IWDG->KR = 0xAAAA; // refresh the watchdog (i.e. load these settings) - IWDG->KR = 0xCCCC; // start the watchdog - _iwdgFeed(); // feed it once and start the task - - taskCreate(_iwdgTask, TASK_MINIMAL_STACK_SIZE, NULL, TASK_PRIORITY_DEFAULT); -} +void watchdogInit() {} +void watchdogStart() {} diff --git a/src/wave.c b/src/wave.c index 6325c7ae..e7a11441 100644 --- a/src/wave.c +++ b/src/wave.c @@ -122,11 +122,6 @@ void speakerInit() { waveNeeded = semaphoreCreate(); semaphoreTake(waveNeeded, 0UL); speakerStop(); - // Set up DMA location and count - DMA2_Channel3->CMAR = (uint32_t)(&waveOutput[0]); - DMA2_Channel3->CNDTR = (uint32_t)WAVE_BUFFER_SIZE; - // Turn on DMA - DMA2_Channel3->CCR |= DMA_CCR_EN; } // speakerParseNumber - Helper for speakerPlayArray @@ -291,7 +286,6 @@ void speakerPlayArray(const char * * rttl) { } // Start the timers of war TIM6->EGR = TIM_EGR_UG; - DMA2->IFCR = DMA_IFCR_CGIF3; TIM6->CR1 |= TIM_CR1_CEN; do { uint16_t wcount; @@ -334,60 +328,12 @@ void speakerShutdown() { semaphoreDelete(waveNeeded); // Turn off the DMA and timer TIM6->CR1 &= ~TIM_CR1_CEN; - DMA2_Channel3->CCR &= ~DMA_CCR_EN; // Wait for the accesses to flush __dsb(); // Clear DAC back to default (0), may cause click and pop? - DAC->DHR12R1 = (uint32_t)0; } // ISR_DMA2_Channel3 - "Transfer complete" ISR that reloads the data array with next samples // Also fires halfway through to load the beginning half (so that any latency will avoid noise // at the update frequency) -IRQ ISR_DMA2_Channel3() { - register int32_t out; - register uint16_t t0, t1, s0, s1, t2, s2; - uint16_t *w; - // Shut off alarm clock - uint32_t flags = DMA2->ISR; - DMA2->IFCR = DMA_IFCR_CGIF3; - // Correct location - if (flags & DMA_ISR_TCIF3) - w = &waveOutput[WAVE_BUFFER_SIZE >> 1]; - else - w = &waveOutput[0]; - t0 = wave[0].sampleTime; - s0 = wave[0].sample; - t1 = wave[1].sampleTime; - s1 = wave[1].sample; - t2 = wave[2].sampleTime; - s2 = wave[2].sample; - for (uint32_t i = (WAVE_BUFFER_SIZE >> 1); i; i--) { - // WAVE CHANNEL 0 - // Overflow is acceptable here - t0 += s0; - // Get sine index by LSRing by 9 - out = (int32_t)SINE_WAVE[t0 >> 9]; - // WAVE CHANNEL 1 - t1 += s1; - out += (int32_t)SINE_WAVE[t1 >> 9]; - // WAVE CHANNEL 2 - t2 += s2; - out += (int32_t)SINE_WAVE[t2 >> 9]; - // We have a total of 14 bits (13+13) to pigeonhole into 10, sign bits are erased - *w++ = (uint16_t)(((out + 4) >> 3) + WAVE_DC_OFFSET); - } - // Write back - wave[0].sampleTime = t0; - wave[1].sampleTime = t1; - wave[2].sampleTime = t2; - if (flags & DMA_ISR_TCIF3) { - wave[0].countdown--; - wave[1].countdown--; - wave[2].countdown--; - // Give control to whichever task is updating sound - bool cs = false; - semaphoreGiveISR(waveNeeded, &cs); - if (cs) _taskYield(); - } -} +IRQ ISR_DMA2_Channel3() {}