/* console.c Implement console communication and commands in FLISP LU systems */ #include "misc.h" #include "stm32f10x_usart.h" #include "stm32f10x_exti.h" #include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" # include "console.h" # ifdef LU4 # include "lu4.h" # endif # ifdef LU3 # include "lu3.h" # endif # ifdef LU2 # include "lu2.h" # endif unsigned char interactive_mode; typedef struct{ unsigned char in; unsigned char out; unsigned char count; unsigned char buff[USARTBUFFSIZE]; }FIFO_TypeDef; static FIFO_TypeDef U1Tx; static int buffer_o; static volatile unsigned char console_state; void enable( void ) __attribute__( ( naked ) ) ; void enable( void ) { __asm ( " cpsie i\n" /* set I=0 */ " bx lr\n" ); } void disable( void ) __attribute__( ( naked ) ) ; void disable( void ) { __asm ( " cpsid i\n" /* set I=1 */ " bx lr\n" ); } /* Static memory */ static CMD cmdbuf[MAX_CMD_BUF]; static unsigned char cmd_in, cmd_out; void initCmd(void) { cmd_in = 0; cmd_out = 0; } void putCmd( PCMD p ) { unsigned char t; t = (cmd_in+1)% MAX_CMD_BUF; if(t == cmd_out) return; /* commad buffer overflow */ else { cmd_in=t; cmdbuf[cmd_in].message = p->message; cmdbuf[cmd_in].p1 = p->p1; cmdbuf[cmd_in].p2 = p->p2; } } PCMD getCmd( void ) { if(cmd_in == cmd_out) return (PCMD) 0; else { cmd_out=(cmd_out + 1)% MAX_CMD_BUF; return( & cmdbuf[cmd_out] ); } } static void bufferInit( FIFO_TypeDef *buffer ) { buffer->count = 0; //0 bytes in buffer buffer->in = 0; //index points to start buffer->out = 0; //index points to start buffer_o = 0; console_state = 0; } static void bufferPut( FIFO_TypeDef *buffer, unsigned char ch ) { disable(); if( buffer->count==USARTBUFFSIZE ){ buffer_o++; enable(); return ; //buffer full } buffer->buff[buffer->in++]=ch; buffer->count++; if(buffer->in==USARTBUFFSIZE) buffer->in=0; //wrap enable(); } static int bufferGet( FIFO_TypeDef *buffer, unsigned char *ch) { if(buffer->count==0) return 0; //buffer empty disable(); *ch=buffer->buff[buffer->out++]; buffer->count--; if(buffer->out==USARTBUFFSIZE) buffer->out=0;//start from beginning enable(); return 1; } void consoleInit( void ) { #ifdef NO_USART_LIB /* Configure the enable and mask bits that control * the NVIC IRQ channel mapped to USART1. */ *((unsigned int *) NVIC_USART1_ISER) |= NVIC_USART1_IRQ_BPOS; /* Enable this interrupt */ /* Setup USART, receive with IRQ, polled transmit, 10 bit (1 startbit, 8 databits */ USART1->brr = 0x2D9; /* Baudrade = 115200 */ USART1->cr3 = 0; USART1->cr2 = 0; /* 1 stopbit */ USART1->cr1 = EN | RXNEIE | TE | RE; #endif bufferInit( &U1Tx ); /* init transmit buffer */ } void consoleOut(unsigned char ch) { bufferPut(&U1Tx, ch); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } static unsigned char hex( unsigned char ch) { switch( ch ) { case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': return ch - '0'; case 'a': case 'b':case 'c':case 'd':case 'e':case 'f': return ch - 'a' + 10; case 'A': case 'B':case 'C':case 'D':case 'E':case 'F': return ch - 'A' + 10; } return 0xFF; } unsigned char binToAscii( unsigned char c ) { switch( c ) { case 0: case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9: return c + '0'; case 0xA: case 0xB:case 0xC:case 0xD:case 0xE:case 0xF: return c + 'A'-10; } return '?'; } void sendAsAscii( unsigned char c ) { if( interactive_mode ){ consoleOut ( binToAscii( (c >> 4) & 0xF)); consoleOut ( binToAscii( c & 0xF )); } } void sendAscii( unsigned char c ) { if( interactive_mode ) consoleOut ( c ); } void sendEOT( void ) { if( interactive_mode ) consoleOut ( '\n' ); } /* console in states: 0: initial 1: W 2: R 3: WM 4: RM RM x1 (accept) x1 valid hex 5: WR 6: RR RR x1 (accept) x1 valid register 7: WM x1 x1 valid hex WM x1 x2 x2 valid hex 8: WM x1 x1 valid hex WM x1 x2 x3 (accept) x2/x3 valid hex 9: WR x1 x1 valid register WR x1 x2 x2 valid register 10: WR x1 x1 valid register WR x1 x2 (accept) x2/x3 valid register */ void USART1_IRQHandler(void) { static unsigned char x1,x2,x3,x4; unsigned char ch; CMD c; #ifdef NO_USART_LIB if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { if (bufferGet(&U1Tx, &ch) == 1)//if buffer read { USART_SendData(USART1, ch); } else//if buffer empty { //disable Transmit Data Register empty interrupt USART_ITConfig(USART1, USART_IT_TXE, DISABLE); } } #else #endif /* If Overrun occures, clear the OVR condition */ if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET) { USART_ClearITPendingBit(USART1, USART_FLAG_ORE); } //if Receive interrupt if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { ch=(unsigned char)USART_ReceiveData(USART1); sendAscii( ch ); switch ( console_state ) { case 0: if( (ch == 'i') || (ch=='I')) { c.message = INTERACTIVE_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'q') || (ch =='Q') ) { c.message = QUIET_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'v') || (ch =='V') ) { c.message = GET_VERSION; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #if (defined LU3) || (defined LU4) if( (ch == 't') || (ch=='T')) { if( ! toggleTestMode() ) { c.message = TEST_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); } break; } #endif if( (ch == 'a') || (ch=='A')) { c.message = FLISP_RESET; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #ifdef LU2 if( (ch == 'd') || (ch=='D')) { c.message = DUMP_MEMORY; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #endif #ifdef LU3 if( (ch == 'b') || (ch=='B')) { c.message = SYSTEM_RESTART; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'd') || (ch=='D')) { c.message = UPDATE_ALL; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'c') || (ch=='C')) { c.message = FLISP_CLK; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'n') || (ch=='N')) { c.message = FLISP_NF; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #endif if( (ch == 'e') || (ch=='E')) { c.message = RUN_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #ifdef LU4 if( (ch == 's') || (ch=='S')) { c.message = STEP_INSTRUCTION; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #endif else if( (ch == 'w')||(ch=='W') ) console_state=1; else if( (ch == 'r')||(ch=='R') ) console_state=2; break; case 1: if( (ch == 'm')||(ch=='M') ) console_state=3; else if( (ch == 'r')||(ch=='R') ) console_state=5; else console_state=0; break; case 2: if( (ch == 'm')||(ch=='M') ) console_state=4; else if( (ch == 'r')||(ch=='R') ) console_state=6; else console_state=0; break; case 3: x1 = hex( ch ); if( x1 != 0xFF) console_state=7; // WM x else console_state=0; break; case 4: x1 = hex( ch ); if( x1 != 0xFF) /* seen RM x */ console_state=11; else console_state=0; break; #if (defined LU3) || (defined LU4) case 5: x1 = translateFlispRegister( ch ); if( x1 != 0xFF) console_state=9; else console_state=0; break; case 6: x1 = translateFlispRegister( ch ); if( x1 != 0xFF) /* Accept RR x1 */ { c.message = REGISTER_READ; c.p1 = x1; c.p2 = 0; putCmd( &c ); } console_state=0; break; #endif case 7: x2 = hex( ch ); if( x2 != 0xFF) /* seen WM x1 x2 */ { console_state=8; }else console_state=0; break; case 8: x3 = hex( ch ); if( x3 != 0xFF) /* seen WM x1|x2 x3 */ console_state=12; else console_state=0; break; case 9: x2 = hex( ch ); if( x2 != 0xFF) /* seen RW x1 x? */ { console_state=10; } else console_state=0; break; case 10: x3 = hex( ch ); if( x3 != 0xFF) /* Accept RW x1 x2|x3 */ { c.message = REGISTER_WRITE; c.p1 = x1; c.p2 = ( x2 << 4 )| x3 ; putCmd( &c ); } console_state=0; break; case 11: x2 = hex( ch ); if( x2 != 0xFF) /* Accept RM xx */ { c.message = MEMORY_READ; c.p1 = ( x1 << 4 )| x2 ; c.p2 = 0; putCmd( &c ); } console_state=0; break; case 12: x4 = hex( ch ); if( x4 != 0xFF) /* accptn WM x1|x2 x3|x4 */ { c.message = MEMORY_WRITE; c.p1 = ( x1 << 4 )| x2 ; c.p2 = ( x3 << 4 )| x4 ; putCmd( &c ); } console_state=0; break; default: console_state=0; } } } /* ST-library replacement */ #define SYSCLK_FREQ 24000000 void initSystick( void ) { #ifdef NOLIB SYS_TICK->ctrl = 0; SYS_TICK->load = SYSCLK_FREQ/1000; SYS_TICK->val = 0; SYS_TICK->ctrl = 7; #else SysTick_Config(SystemCoreClock / 1000); /* Initialize SysTick - 1msec */ #endif } #ifdef NOLIB /* static */ void SetSysClockTo24(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/ /* Enable HSE */ RCC->CR |= ((uint32_t)RCC_CR_HSEON); /* Wait till HSE is ready and if Time out is reached exit */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY; StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET) { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01) { #if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_ACR_PRFTBE; /* Flash 0 wait state */ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0; #endif /* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK */ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1; #ifdef STM32F10X_CL /* Configure PLLs ------------------------------------------------------*/ /* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */ RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL6); /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */ RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC); RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10); /* Enable PLL2 */ RCC->CR |= RCC_CR_PLL2ON; /* Wait till PLL2 is ready */ while((RCC->CR & RCC_CR_PLL2RDY) == 0) { } #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6); #else /* PLL configuration: = (HSE / 2) * 6 = 24 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6); #endif /* STM32F10X_CL */ /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } /* Select PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { } } else { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */ while(1) { } } } void SystemInit (void) { /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ RCC->CFGR &= (uint32_t)0xF8FF0000; /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (uint32_t)0xFF80FFFF; /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x009F0000; /* Reset CFGR2 register */ RCC->CFGR2 = 0x00000000; /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ /* Configure the Flash Latency cycles and enable prefetch buffer */ SetSysClock(); SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ } #endif