From b6674cd738cc22e61ea34cb659750ef45ce01df4 Mon Sep 17 00:00:00 2001 From: iperry Date: Fri, 25 Dec 2009 08:39:24 +0000 Subject: Fixed delayMicroseconds, changed serial interface, added an (untested) runtime check for pwm/serial collision, moved more headers around. git-svn-id: https://leaflabs.googlecode.com/svn/trunk/library@79 749a229e-a60e-11de-b98f-4500b42dc123 --- README.txt | 14 +------ src/lib/gpio.c | 8 +--- src/lib/gpio.h | 28 +++++--------- src/lib/systick.h | 2 +- src/lib/timers.c | 37 +++++++++++++++++++ src/lib/timers.h | 1 + src/lib/usart.h | 75 -------------------------------------- src/main.cpp | 9 ++--- src/wiring/comm/HardwareSerial.cpp | 3 ++ src/wiring/time.c | 23 +++--------- src/wiring/time.h | 14 +++++++ src/wiring/wiring.c | 9 ++--- 12 files changed, 82 insertions(+), 141 deletions(-) diff --git a/README.txt b/README.txt index 802aa24..17f813e 100644 --- a/README.txt +++ b/README.txt @@ -7,22 +7,10 @@ * D15 is mapped to pin number 38. This is to retain compatiblity with the * Arduino API, where digitalWrite() on pins 14-19 map to analog A0-A5 * - * Fix serial/timer - * Add external itnerrupts - * Redo serial api - * - * Order some shields - * buy some toner - * LARW BOOK - * - * - * wtf is smba/smbal? - * serial.print - * - * 5v tolerance * * TODO: * Using OSC32_IN/OSC32_OUT pins as GPIO ports PC14/PC15 152/995 + * Runtime check for AF collisions on pins (eg serial and pwm). * */ /* 51 GPIOs in general diff --git a/src/lib/gpio.c b/src/lib/gpio.c index 1e42d4d..f03c4fa 100644 --- a/src/lib/gpio.c +++ b/src/lib/gpio.c @@ -23,10 +23,6 @@ * @brief GPIO initialization routine */ -#ifndef _GPIO_H_ -#define _GPIO_H_ - -#endif #include "libmaple.h" #include "stm32f10x_rcc.h" #include "gpio.h" @@ -36,11 +32,11 @@ void gpio_init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | - RCC_APB2Periph_AFIO, + RCC_APB2Periph_AFIO, ENABLE); } -void gpio_set_mode(GPIO_Port* port, uint8_t gpio_pin, uint8_t mode) { +void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, uint8 mode) { uint32_t tmp; uint32_t shift = POS(gpio_pin % 8); GPIOReg CR; diff --git a/src/lib/gpio.h b/src/lib/gpio.h index bc9bdde..5e7cf29 100644 --- a/src/lib/gpio.h +++ b/src/lib/gpio.h @@ -58,25 +58,17 @@ #define GPIO_MODE_INPUT_PD (0x02 << 2) #define GPIO_MODE_INPUT_PU (0x02 << 2) -//#define INPUT_ANALOG GPIO_MODE_INPUT_ANALOG -//#define INPUT_DIGITAL GPIO_MODE_INPUT_FLOATING -//#define INPUT_FLOATING GPIO_MODE_INPUT_FLOATING -//#define INPUT_PULLDOWN GPIO_MODE_INPUT_PD -//#define INPUT_PULLUP GPIO_MODE_INPUT_PU -//#define INPUT GPIO_MODE_INPUT_FLOATING -//#define OUTPUT GPIO_MODE_OUTPUT_PP - typedef struct { - volatile uint32_t CRL; // Port configuration register low - volatile uint32_t CRH; // Port configuration register high - volatile uint32_t IDR; // Port input data register - volatile uint32_t ODR; // Port output data register - volatile uint32_t BSRR; // Port bit set/reset register - volatile uint32_t BRR; // Port bit reset register - volatile uint32_t LCKR; // Port configuration lock register + volatile uint32 CRL; // Port configuration register low + volatile uint32 CRH; // Port configuration register high + volatile uint32 IDR; // Port input data register + volatile uint32 ODR; // Port output data register + volatile uint32 BSRR; // Port bit set/reset register + volatile uint32 BRR; // Port bit reset register + volatile uint32 LCKR; // Port configuration lock register } GPIO_Port; -typedef volatile uint32_t* GPIOReg; +typedef volatile uint32* GPIOReg; #define POS_MASK(shift) (~(0xF << shift)) #define POS(val) (val << 2) @@ -86,9 +78,9 @@ extern "C"{ #endif void gpio_init(void); -void gpio_set_mode(GPIO_Port* port, uint8_t gpio_pin, uint8_t mode); +void gpio_set_mode(GPIO_Port* port, uint8 gpio_pin, uint8 mode); -static inline void gpio_write_bit(GPIO_Port *port, uint8_t gpio_pin, uint8_t val) { +static inline void gpio_write_bit(GPIO_Port *port, uint8 gpio_pin, uint8 val) { if (val){ port->BSRR = BIT(gpio_pin); } else { diff --git a/src/lib/systick.h b/src/lib/systick.h index 3d846ef..61789c4 100644 --- a/src/lib/systick.h +++ b/src/lib/systick.h @@ -51,7 +51,7 @@ extern "C"{ void systick_init(void); static inline uint32_t systick_get_count(void) { - return (uint32_t)SYSTICK_CNT; + return (uint32_t)*(volatile uint32*)SYSTICK_CNT; } #ifdef __cplusplus diff --git a/src/lib/timers.c b/src/lib/timers.c index 2161d84..1e95f41 100644 --- a/src/lib/timers.c +++ b/src/lib/timers.c @@ -152,3 +152,40 @@ void timers_disable(void) { timer->CR1 = 0; } } + +void timers_disable_channel(uint8 timer_num, uint8 channel) { + Timer *timer; + switch (timer_num) { + case 1: + timer = (Timer*)TIMER1_BASE; + break; + case 2: + timer = (Timer*)TIMER2_BASE; + break; + case 3: + timer = (Timer*)TIMER3_BASE; + break; + case 4: + timer = (Timer*)TIMER4_BASE; + break; + default: + ASSERT(0); + } + + switch (channel) { + case 1: + timer->CCER &= ~(0x1); + break; + case 2: + timer->CCER &= ~(0x10); + break; + case 3: + timer->CCER &= ~(0x100); + break; + case 4: + timer->CCER &= ~(0x1000); + break; + default: + ASSERT(0); + } +} diff --git a/src/lib/timers.h b/src/lib/timers.h index 9147fd4..18b0afb 100644 --- a/src/lib/timers.h +++ b/src/lib/timers.h @@ -117,6 +117,7 @@ typedef volatile uint32_t* TimerCCR; * */ void timer_init(uint8_t, uint16_t); void timers_disable(void); +void timers_disable_channel(uint8, uint8); /* Turn on PWM with duty_cycle on the specified channel in timer. * This function takes in a pointer to the corresponding CCR diff --git a/src/lib/usart.h b/src/lib/usart.h index 4d0c586..b9efdd5 100644 --- a/src/lib/usart.h +++ b/src/lib/usart.h @@ -26,81 +26,6 @@ #ifndef _USART_H_ #define _USART_H_ -/* Transmit procedure: - * 1. Enable the USART by writing the UE bit in USART_CR1 register to 1. - * - * 2. Program the M bit in USART_CR1 to define the word length. - * - * 3. Program the number of stop bits in USART_CR2. - * - * 4. Select DMA enable (DMAT) in USART_CR3 if Multi buffer Communication is - * to take place. Configure the DMA register as explained in multibuffer - * communication. - * - * 5. Select the desired baud rate using the USART_BRR register. - * - * 6. Set the TE bit in USART_CR1 to send an idle frame as first transmission. - * - * 7. Write the data to send in the USART_DR register (this clears the TXE - * bit). Repeat this for each data to be transmitted in case of single buffer. - * - * 8. After writing the last data into the USART_DR register, wait until TC=1. - * This indicates that the transmission of the last frame is complete. This is - * required for instance when the USART is disabled or enters the Halt mode to - * avoid corrupting the last transmission. - * - * Single byte communication - * Clearing the TXE bit is always performed by a write to the data register. - * - * The TXE bit is set by hardware and it indicates: - * ? The data has been moved from TDR to the shift register and the data transmission has - * started. - * ? The TDR register is empty. - * ? The next data can be written in the USART_DR register without overwriting the - * previous data. - * This flag generates an interrupt if the TXEIE bit is set. - * - * When a transmission is taking place, a write instruction to the USART_DR - * register stores the data in the TDR register and which is copied in the - * shift register at the end of the current transmission. - * - * When no transmission is taking place, a write instruction to the USART_DR - * register places the data directly in the shift register, the data - * transmission starts, and the TXE bit is immediately set. - * - * If a frame is transmitted (after the stop bit) and the TXE bit is set, the - * TC bit goes high. An interrupt is generated if the TCIE bit is set in the - * USART_CR1 register. After writing the last data into the USART_DR register, - * it is mandatory to wait for TC=1 before disabling the USART or causing the - * microcontroller to enter the low power mode (see Figure 241: TC/TXE behavior - * when transmitting). - * - * Clearing the TC bit is performed by the following software sequence: - * 1. A read from the USART_SR register - * 2. A write to the USART_DR register - * - * - * For now, use 8N1 - * - * Baud rate is generated by programming the mantissa and fraction values of - * USARTDIV - * - * baud = fck / 16*USARTDIV - * Fck = PLK1 for USART2 and USART3 = 36MHz - * Fck = PCLK2 for USART1 = 72MHz - * - * Baud Actual USARTDIV_36MHZ Error USARTDIV_72MHZ Error - * 2400 2.400 937.5 0% 1875 0% - * 9600 9.600 234.375 0% 468.75 0% - * 19200 19.2 117.1875 0% 234.375 0% - * 57600 57.6 39.0625 0% 78.125 0.% - * 115200 115.384 19.5 0.15% 39.0625 0% - * 230400 230.769 9.75 0.16% 19.5 0.16% - * 460800 461.538 4.875 0.16% 9.75 0.16% - * 921600 923.076 2.4375 0.16% 4.875 0.16% - * 225000 2250 1 0% 2 0% - * - * */ #define NR_USARTS 0x3 #ifdef __cplusplus diff --git a/src/main.cpp b/src/main.cpp index cf79329..8c90b7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,9 +3,6 @@ #include "math.h" #include "usb.h" -void setup(); -void loop(); - int ledPin = 13; uint8_t bytes_in; @@ -26,6 +23,7 @@ void setup() pinMode(6, PWM); pwmWrite(6, 0x8000); + pinMode(7, OUTPUT); Serial2.println("setup end"); @@ -37,8 +35,9 @@ void setup() int toggle = 0; -char* testMsg = "0123456\n"; -void loop() { +const char* testMsg = "hello world!\n"; + +static inline void loop() { toggle ^= 1; digitalWrite(ledPin, toggle); delay(1000); diff --git a/src/wiring/comm/HardwareSerial.cpp b/src/wiring/comm/HardwareSerial.cpp index 84eb4c7..3d0a0ce 100644 --- a/src/wiring/comm/HardwareSerial.cpp +++ b/src/wiring/comm/HardwareSerial.cpp @@ -27,6 +27,7 @@ #include "HardwareSerial.h" #include "usart.h" #include "gpio.h" +#include "timers.h" #define USART1_TX_PORT GPIOA_BASE #define USART1_TX_PIN 9 @@ -75,6 +76,8 @@ void HardwareSerial::begin(uint32_t baud) { case 2: gpio_set_mode(USART2_TX_PORT, USART2_TX_PIN, GPIO_MODE_AF_OUTPUT_PP); gpio_set_mode(USART2_RX_PORT, USART2_RX_PIN, GPIO_MODE_INPUT_FLOATING); + /* Turn off any pwm */ + timers_disable_channel(2, 3); break; case 3: gpio_set_mode(USART3_TX_PORT, USART3_TX_PIN, GPIO_MODE_AF_OUTPUT_PP); diff --git a/src/wiring/time.c b/src/wiring/time.c index 1a91b5e..164d978 100644 --- a/src/wiring/time.c +++ b/src/wiring/time.c @@ -28,7 +28,7 @@ #include "time.h" #define CYCLES_PER_MICROSECOND 72 -#define THE_SECRET_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING 42 +#define FUDGE 42 extern volatile uint32_t systick_timer_millis; @@ -47,26 +47,13 @@ void delay(unsigned long ms) } -#define MAGIC 4096 -/* HZ = 1000 - * n HZ*/ + +#if 1 void delayMicroseconds(uint32_t us) { uint32_t target; uint32_t last, cur, count; - -#if 0 - asm volatile("mov r0, %[count] \n\t" -"1: \n\t" - "subs r0, r0, #1 \n\t" - "bne 1b" - : - : [count] "r" (count) - : "r0", "cc"); -#endif - -#if 1 /* fudge factor hacky hack hack for function overhead */ - target = us * CYCLES_PER_MICROSECOND - THE_SECRET_TO_LIFE_THE_UNIVERSE_AND_EVERYTHING; + target = us * CYCLES_PER_MICROSECOND - FUDGE; /* Get current count */ last = systick_get_count(); @@ -81,5 +68,5 @@ void delayMicroseconds(uint32_t us) { } last = cur; } -#endif } +#endif diff --git a/src/wiring/time.h b/src/wiring/time.h index a97310a..68b3901 100644 --- a/src/wiring/time.h +++ b/src/wiring/time.h @@ -41,6 +41,20 @@ void delay(unsigned long ms); /* Delay for us microseconds */ void delayMicroseconds(uint32_t us); +#if 0 +static inline void delay_us(uint32 us) { + us *= 12; + asm volatile("mov r0, %[us] \n\t" + "subs r0, #2 \n\t" +"1: \n\t" + "subs r0, r0, #1 \n\t" + "bne 1b" + : + : [us] "r" (us) + : "r0", "cc"); + +} +#endif #ifdef __cplusplus } // extern "C" #endif diff --git a/src/wiring/wiring.c b/src/wiring/wiring.c index cecca20..04de78a 100644 --- a/src/wiring/wiring.c +++ b/src/wiring/wiring.c @@ -47,13 +47,12 @@ void init(void) { gpio_init(); - /* off for debug */ -// adc_init(); + adc_init(); timer_init(1, 1); -// timer_init(2, 1); -// timer_init(3, 1); -// timer_init(4, 1); + timer_init(2, 1); + timer_init(3, 1); + timer_init(4, 1); } void NVIC_Configuration(void) { -- cgit v1.2.3