361 lines
9.7 KiB
C

/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* Utilities - reimplementation of jshardware bits in minimal flash
* ----------------------------------------------------------------------------
*/
#include "platform_config.h"
#ifdef USB
#ifdef STM32F1
#include "usb_utils.h"
#include "usb_lib.h"
#include "usb_conf.h"
#include "usb_pwr.h"
#include "usb_istr.h"
#endif
#ifdef STM32F4
#include "usb_regs.h"
#include "usb_defines.h"
#include "usbd_conf.h"
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usb_conf.h"
#include "usbd_desc.h"
#include "usb_core.h"
#include "usbd_core.h"
#include "usbd_cdc_core.h"
#include "usb_dcd_int.h"
#endif
#endif
#include "jshardware.h"
#define BUFFERMASK 8191
char rxBuffer[BUFFERMASK+1];
int rxHead=0, rxTail=0;
char txBuffer[BUFFERMASK+1];
int txHead=0, txTail=0;
uint16_t stmPin(Pin ipin) {
JsvPinInfoPin pin = JSH_PIN0;
if (JSH_PORTF_OFFSET >= 0 && ipin > JSH_PORTF_OFFSET) pin = ipin-JSH_PORTF_OFFSET;
else if (JSH_PORTE_OFFSET >= 0 && ipin > JSH_PORTE_OFFSET) pin = ipin-JSH_PORTE_OFFSET;
else if (JSH_PORTD_OFFSET >= 0 && ipin > JSH_PORTD_OFFSET) pin = ipin-JSH_PORTD_OFFSET;
else if (JSH_PORTC_OFFSET >= 0 && ipin > JSH_PORTC_OFFSET) pin = ipin-JSH_PORTC_OFFSET;
else if (JSH_PORTB_OFFSET >= 0 && ipin > JSH_PORTB_OFFSET) pin = ipin-JSH_PORTB_OFFSET;
else if (JSH_PORTA_OFFSET >= 0 && ipin > JSH_PORTA_OFFSET) pin = ipin-JSH_PORTA_OFFSET;
return 1 << pin;
}
GPIO_TypeDef *stmPort(Pin ipin) {
if (JSH_PORTF_OFFSET >= 0 && ipin > JSH_PORTF_OFFSET) return GPIOF;
else if (JSH_PORTE_OFFSET >= 0 && ipin > JSH_PORTE_OFFSET) return GPIOE;
else if (JSH_PORTD_OFFSET >= 0 && ipin > JSH_PORTD_OFFSET) return GPIOD;
else if (JSH_PORTC_OFFSET >= 0 && ipin > JSH_PORTC_OFFSET) return GPIOC;
else if (JSH_PORTB_OFFSET >= 0 && ipin > JSH_PORTB_OFFSET) return GPIOB;
//else if (ipin > JSH_PORTA_OFFSET) return GPIOA;
return GPIOA;
}
bool jshPinGetValue(Pin pin) {
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = stmPin(pin);
#ifdef STM32API2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
#endif
GPIO_Init(stmPort(pin), &GPIO_InitStructure);
return GPIO_ReadInputDataBit(stmPort(pin), stmPin(pin)) != 0;
}
void jshPinOutput(Pin pin, bool value) {
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = stmPin(pin);
#ifdef STM32API2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
#else
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
#endif
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(stmPort(pin), &GPIO_InitStructure);
#ifdef STM32API2
if (value)
GPIO_SetBits(stmPort(pin), stmPin(pin));
else
GPIO_ResetBits(stmPort(pin), stmPin(pin));
#else
if (value)
stmPort(pin)->BSRR = stmPin(pin);
else
stmPort(pin)->BRR = stmPin(pin);
#endif
}
#ifdef STM32F4
/******************************************************************************/
/* STM32 Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32xxx.s). */
/******************************************************************************/
/*******************************************************************************
* Function Name : PPP_IRQHandler
* Description : This function handles PPP interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
/*void PPP_IRQHandler(void)
{
}*/
/**
* @brief This function handles EXTI15_10_IRQ Handler.
* @param None
* @retval None
*/
#ifdef USE_USB_OTG_FS
void OTG_FS_WKUP_IRQHandler(void)
{
if(USB_OTG_dev.cfg.low_power)
{
*(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
SystemInit();
USB_OTG_UngateClock(&USB_OTG_dev);
}
EXTI_ClearITPendingBit(EXTI_Line18);
}
#endif
/**
* @brief This function handles EXTI15_10_IRQ Handler.
* @param None
* @retval None
*/
#ifdef USE_USB_OTG_HS
void OTG_HS_WKUP_IRQHandler(void)
{
if(USB_OTG_dev.cfg.low_power)
{
*(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
SystemInit();
USB_OTG_UngateClock(&USB_OTG_dev);
}
EXTI_ClearITPendingBit(EXTI_Line20);
}
#endif
/**
* @brief This function handles OTG_HS Handler.
* @param None
* @retval None
*/
#ifdef USE_USB_OTG_HS
void OTG_HS_IRQHandler(void)
#else
void OTG_FS_IRQHandler(void)
#endif
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
}
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED
extern uint32_t USBD_OTG_EP1IN_ISR_Handler (USB_OTG_CORE_HANDLE *pdev);
extern uint32_t USBD_OTG_EP1OUT_ISR_Handler (USB_OTG_CORE_HANDLE *pdev);
/**
* @brief This function handles EP1_IN Handler.
* @param None
* @retval None
*/
void OTG_HS_EP1_IN_IRQHandler(void)
{
USBD_OTG_EP1IN_ISR_Handler (&USB_OTG_dev);
}
/**
* @brief This function handles EP1_OUT Handler.
* @param None
* @retval None
*/
void OTG_HS_EP1_OUT_IRQHandler(void)
{
USBD_OTG_EP1OUT_ISR_Handler (&USB_OTG_dev);
}
#endif
#else // STM32F4
void USB_LP_CAN1_RX0_IRQHandler(void)
{
USB_Istr();
}
void USBWakeUp_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line18);
}
#endif // not STM32F4
unsigned int SysTickUSBWatchdog = SYSTICKS_BEFORE_USB_DISCONNECT;
void jshKickUSBWatchdog() {
SysTickUSBWatchdog = 0;
}
void SysTick_Handler(void) {
if (SysTickUSBWatchdog < SYSTICKS_BEFORE_USB_DISCONNECT) {
SysTickUSBWatchdog++;
}
}
bool jshIsUSBSERIALConnected() {
return SysTickUSBWatchdog < SYSTICKS_BEFORE_USB_DISCONNECT;
}
int jshGetCharToTransmit(IOEventFlags device) {
if (txHead == txTail) return -1;
char d = txBuffer[txTail];
txTail = (txTail+1) & BUFFERMASK;
return d;
}
void jshPushIOCharEvent(IOEventFlags channel, char charData) {
rxBuffer[rxHead] = charData;
rxHead = (rxHead+1) & BUFFERMASK;
//if (rxHead == rxTail) weHaveOverFlowed();
}
bool jshHasEventSpaceForChars(int n) {
return true;
}
int getc() {
if (rxHead == rxTail) return -1;
unsigned char d = (unsigned char)rxBuffer[rxTail];
rxTail = (rxTail+1) & BUFFERMASK;
return d;
}
unsigned char getc_blocking() {
int c = getc();
while (c<0) c=getc();
return c;
}
void putc(char charData) {
txBuffer[txHead] = charData;
txHead = (txHead+1) & BUFFERMASK;
}
void initHardware() {
#if defined(STM32F3)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA |
RCC_AHBPeriph_GPIOB |
RCC_AHBPeriph_GPIOC |
RCC_AHBPeriph_GPIOD |
RCC_AHBPeriph_GPIOE |
RCC_AHBPeriph_GPIOF, ENABLE);
#elif defined(STM32F2) || defined(STM32F4)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
RCC_AHB1Periph_GPIOB |
RCC_AHB1Periph_GPIOC |
RCC_AHB1Periph_GPIOD |
RCC_AHB1Periph_GPIOE |
RCC_AHB1Periph_GPIOF |
RCC_AHB1Periph_GPIOG |
RCC_AHB1Periph_GPIOH, ENABLE);
#else
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_ADC1 |
RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF |
RCC_APB2Periph_GPIOG |
RCC_APB2Periph_AFIO, ENABLE);
#endif
jshPinOutput(LED1_PININDEX, 1);
jshPinOutput(LED2_PININDEX, 1);
#ifdef BTN1_PININDEX
#if defined(BTN1_PINSTATE)
#if BTN1_PINSTATE==JSHPINSTATE_GPIO_IN_PULLDOWN
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = stmPin(BTN1_PININDEX);
GPIO_Init(stmPort(BTN1_PININDEX), &GPIO_InitStructure);
#else
#error Unknown pin state for BTN1
#endif
#endif
#endif
// if button is not set, jump to this address
if (jshPinGetValue(BTN1_PININDEX) != BTN1_ONSTATE) {
unsigned int *ResetHandler = (unsigned int *)(0x08000000 + BOOTLOADER_SIZE + 4);
void (*startPtr)() = *ResetHandler;
startPtr();
}
// PREEMPTION
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
RCC_PCLK1Config(RCC_HCLK_Div2); // PCLK1 must be >13 Mhz for USB to work (see STM32F103 C/D/E errata)
RCC_PCLK2Config(RCC_HCLK_Div4);
#ifdef ESPRUINOBOARD
#ifndef DEBUG
// reclaim A13 and A14 for the LEDs
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); // Disable JTAG/SWD so pins are available
#endif
#endif
/* System Clock */
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick_Config(SYSTICK_RANGE-1); // 24 bit
NVIC_SetPriority(SysTick_IRQn, 0); // Super high priority
#if defined(STM32F1) || defined(STM32F3)
USB_Init_Hardware();
USB_Init();
#else
USBD_Init(&USB_OTG_dev,
#ifdef USE_USB_OTG_HS
USB_OTG_HS_CORE_ID,
#else
USB_OTG_FS_CORE_ID,
#endif
&USR_desc,
&USBD_CDC_cb,
&USR_cb);
#endif
}