INL-retro-progdump/firmware/source/main.c

157 lines
4.4 KiB
C

#include "usb.h"
#include "io.h"
#include "buffer.h"
#include "bootload.h"
#include "jtag.h"
#ifdef AVR_CORE
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "usbdrv.h"
#endif
#ifdef STM_CORE
#include <stm32f0xx.h>
#include "../source_stm_only/stm_init.h"
#endif
int main(void)
{
#ifdef AVR_CORE
//set watch dog timer with 1 second timer
wdt_enable(WDTO_1S);
/* Even if you don't use the watchdog, turn it off here. On newer devices,
* the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
*/
/* RESET status: all port bits are inputs without pull-up.
* That's the way we need D+ and D-. Therefore we don't need any
* additional hardware initialization.
*/
//initialize V-usb driver before interupts enabled and entering main loop
usbInit();
//disconnect from host enforce re-enumeration, interupts must be disabled during this.
usbDeviceDisconnect();
//fake USB disconnect for over 250ms
uint8_t index = 0;
while(--index){ //loop 256 times
wdt_reset(); //keep wdt happy during this time
_delay_ms(1); //delay 256msec
}
//reconnect to host
usbDeviceConnect();
//enable interrupts
sei();
#endif
#ifdef STM_CORE
//remap system memory (including vector table)
// SYSCFG->CFGR1 = 0x00000002; //boot value (BOOT1:0 = 0b10
// SYSCFG->CFGR1 = 0x00000001; //map sysmem bootloader to 0x00000000
//SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE_ | 0x0001;
//jump to bootloader
// jump_to_bootloader();
// jump_to_addr(0x1FFFC519);
//System is running at reset defaults
//Default clock is in operation
//Change system clock as needed
init_clock();
//now enable GPIO and set
//trying to move to 48Mhz clock for all STM32 cores
//If >24Mhz SYSCLK, must add wait state to flash
//can also enable prefetch buffer
FLASH->ACR = FLASH_ACR_PRFTBE | 0x0001;
//switch to 48Mhz
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_CFGR_SW_PLL;
//Initialize periphery clocks as needed
init_usb_clock();
//Initialize WDT, core features, etc
//enable interrupts
__enable_irq(); //clear's processor PRIMASK register bit to allow interrupts to be taken
//I think this gets done automatically when enabling individual IRQs
//Initialize io, periphery, etc
//setup LED as outputs and turn them on
//setup user switch as input
init_usb();
//Initialize board/system
#endif
//intialize i/o and LED to pullup state
io_reset();
//this is just a quick hack to allow measuring HSE with a scope w/o loading the circuit with probes.
//#define DRIVE_MCO
#ifdef DRIVE_MCO
//drive HSE (8Mhz) divided by 8 = 1Mhz for crystal load capacitor calibration
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_MCOPRE) | RCC_CFGR_MCOPRE_DIV8; /* MCO prescaler = div 8 */
//RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_MCOPRE) | RCC_CFGR_MCOPRE_DIV16; /* MCO prescaler = div 16 */
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_MCO) | RCC_CFGR_MCO_HSE; /* MCO source HSE */
//enable GPIO pin PA8 MCO AF0
//RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
//CTL_ENABLE();
nes_init();
//GPIOA->MODER = MODER_AF << (2*8U); //set PA8 to AF
GPIOA->MODER = 0x28020000; //set PA14, PA13, (SWD) & PA8 (MCO) to AF
//AF0 is the default value of GPIOx_AFRH/L registers so MCO is already selected as AF in use
#endif
//initialize jtag engine to be off
pbje_status = PBJE_OFF;
//=================
//MAIN LOOP
//=================
while (1) {
#ifdef AVR_CORE
//pet the watch doggie to keep him happy
wdt_reset();
//must call at regular intervals no longer than 50msec
//keeps 8Byte EP buffer moving from what I understand
usbPoll();
#endif
//check buffer status' and instruct them to
//flash/dump as needed to keep data moving
//currently assuming this operation doesn't take longer
//than 50msec to meet usbPoll's req't
//considering using a timer counter interupt to call
//usbPoll more often but going to see how speed is
//impacted first..
//256Bytes * 20usec Tbp = 5.12msec programming time
//+ cpu operations that can't be hid behind flash wait time
//another thought would be to call usbPoll mid programming
//a few times to prevent incoming data from being delayed too long
update_buffers();
//if paul's basic jtag engine "PBJE" is running, main
//thread needs to call engine at periodic intervals to keep it
//running.
if (pbje_status != PBJE_OFF) {
jtag_run_pbje();
}
}
}