/************************************************************************************//** ** \brief Transmits a packet formatted for the communication interface. ** \param data Pointer to byte array with data that it to be transmitted. ** \param len Number of bytes that are to be transmitted. ** \return none. ** ****************************************************************************************/ void UsbTransmitPacket(blt_int8u *data, blt_int8u len) { blt_int16u data_index; blt_bool result; /* verify validity of the len-parameter */ ASSERT_RT(len <= BOOT_COM_USB_TX_MAX_DATA); /* first transmit the length of the packet */ result = UsbTransmitByte(len); ASSERT_RT(result == BLT_TRUE); /* transmit all the packet bytes one-by-one */ for (data_index = 0; data_index < len; data_index++) { /* keep the watchdog happy */ CopService(); /* write byte */ result = UsbTransmitByte(data[data_index]); ASSERT_RT(result == BLT_TRUE); } /* start the transmission */ UsbTransmitPipeBulkIN(); } /*** end of UsbTransmitPacket ***/
/************************************************************************************//** ** \brief Returns the number of data entries currently present in the fifo. ** \param handle Identifies the fifo that is to be scanned. ** \return Number of data entries in the fifo if successful, otherwise 0. ** ****************************************************************************************/ static blt_int8u UsbFifoMgrScan(blt_int8u handle) { /* check the validity of the handle parameter */ ASSERT_RT(handle < FIFO_MAX_BUFFERS); /* read and return the number of data entries */ return fifoCtrl[handle].entries; } /*** end of UsbFifoMgrScan ***/
/************************************************************************************//** ** \brief Stores data that was received on the Bulk OUT pipe in the fifo. ** \param data Pointer to buffer with the newly received data ** \param len Number of received data bytes. ** \return none. ** ****************************************************************************************/ static void UsbReceivePipeBulkOUT(blt_int8u *data, blt_int32u len) { blt_int32u byte_counter; blt_bool result; blt_int32u rxReadIdx; /* determine read index for the rx buffer */ rxReadIdx = (uint32_t)(data - g_pui8USBRxBuffer); /* store the received data in the reception fifo */ for (byte_counter=0; byte_counter<len; byte_counter++) { /* add the data to the fifo */ result = UsbFifoMgrWrite(fifoPipeBulkOUT.handle, g_pui8USBRxBuffer[rxReadIdx]); /* verify that the fifo wasn't full */ ASSERT_RT(result == BLT_TRUE); /* increment index with wrapping */ rxReadIdx++; if (rxReadIdx >= BULK_BUFFER_SIZE) { rxReadIdx = 0; } } } /*** end of UsbReceivePipeBulkOUT ***/
/************************************************************************************//** ** \brief Initializes the USB communication interface. ** \return none. ** ****************************************************************************************/ void UsbInit(void) { /* initialize the FIFO manager */ UsbFifoMgrInit(); /* place 2 buffers under FIFO management */ fifoPipeBulkIN.handle = UsbFifoMgrCreate(fifoPipeBulkIN.data, FIFO_PIPE_SIZE); fifoPipeBulkOUT.handle = UsbFifoMgrCreate(fifoPipeBulkOUT.data, FIFO_PIPE_SIZE); /* validate fifo handles */ ASSERT_RT( (fifoPipeBulkIN.handle != FIFO_ERR_INVALID_HANDLE) && \ (fifoPipeBulkOUT.handle != FIFO_ERR_INVALID_HANDLE) ); /* initialize the transmit and receive buffers */ USBBufferInit(&g_sTxBuffer); USBBufferInit(&g_sRxBuffer); /* pass our device information to the USB library and place the device on the bus */ instanceHandle = USBDBulkInit(0, &g_sBulkDevice); ASSERT_RT(instanceHandle != BLT_NULL); } /*** end of UsbInit ***/
/************************************************************************************//** ** \brief Checks if there is still data left to transmit and if so submits it ** for transmission with the USB endpoint. ** \return none. ** ****************************************************************************************/ static void UsbTransmitPipeBulkIN(void) { tUSBRingBufObject txRing; blt_int32u txSpace; blt_int32u txWriteIdx; blt_int8u nr_of_bytes_for_tx_endpoint; blt_int8u byte_counter; blt_int8u byte_value; blt_bool result; /* read how many bytes should be transmitted */ nr_of_bytes_for_tx_endpoint = UsbFifoMgrScan(fifoPipeBulkIN.handle); /* only continue if there is actually data left to transmit */ if (nr_of_bytes_for_tx_endpoint == 0) { return; } /* get information about the USB transmit buffer */ USBBufferInfoGet(&g_sTxBuffer, &txRing); /* determine how many bytes will still fit in the tx buffer */ txSpace = USBBufferSpaceAvailable(&g_sTxBuffer); /* only transmit the amount of bytes that will fit in the tx buffer */ if (nr_of_bytes_for_tx_endpoint > txSpace) { nr_of_bytes_for_tx_endpoint = txSpace; } /* determine write index for the tx buffer */ txWriteIdx = txRing.ui32WriteIndex; /* copy the transmit data to the transmit buffer */ for (byte_counter=0; byte_counter < nr_of_bytes_for_tx_endpoint; byte_counter++) { /* obtain data from the fifo */ result = UsbFifoMgrRead(fifoPipeBulkIN.handle, &byte_value); ASSERT_RT(result == BLT_TRUE); /* store it in the transmit buffer */ g_pui8USBTxBuffer[txWriteIdx] = byte_value; /* increment index with wrapping */ txWriteIdx++; if (txWriteIdx >= BULK_BUFFER_SIZE) { txWriteIdx = 0; } } /* inform the usb library that new data are ready for transmission */ USBBufferDataWritten(&g_sTxBuffer, nr_of_bytes_for_tx_endpoint); } /*** end of UsbTransmitPipeBulkIN ***/
/************************************************************************************//** ** \brief Retrieves data from the fifo. ** \param handle Identifies the fifo to read data from. ** \param data Pointer to where the read data is to be stored. ** \return BLT_TRUE if the data was successfully read from the fifo, BLT_FALSE ** otherwise. ** ****************************************************************************************/ static blt_bool UsbFifoMgrRead(blt_int8u handle, blt_int8u *data) { /* check the validity of the handle parameter */ ASSERT_RT(handle < FIFO_MAX_BUFFERS); /* check if fifo is empty */ if (fifoCtrl[handle].entries == 0) { return BLT_FALSE; } /* read the data */ *data = *fifoCtrl[handle].readptr; /* data read so update number of entries */ fifoCtrl[handle].entries--; /* update read pointer */ fifoCtrl[handle].readptr++; /* check end of fifo */ if (fifoCtrl[handle].readptr > fifoCtrl[handle].endptr) { /* set read pointer to start of the cyclic fifo */ fifoCtrl[handle].readptr = fifoCtrl[handle].startptr; } /* still here so all is good */ return BLT_TRUE; } /*** end of UsbFifoMgrRead ***/
/************************************************************************************//** ** \brief Stores data in the fifo. ** \param handle Identifies the fifo to write data to. ** \param data Pointer to the data that is to be written to the fifo. ** \return BLT_TRUE if the data was successfully stored in the fifo, BLT_FALSE ** otherwise. ** ****************************************************************************************/ static blt_bool UsbFifoMgrWrite(blt_int8u handle, blt_int8u data) { /* check the validity of the handle parameter */ ASSERT_RT(handle < FIFO_MAX_BUFFERS); /* check if fifo is full */ if (fifoCtrl[handle].entries == fifoCtrl[handle].length) { return BLT_FALSE; } /* copy data to fifo */ *fifoCtrl[handle].writeptr = data; /* data written so update number of entries */ fifoCtrl[handle].entries++; /* update write pointer */ fifoCtrl[handle].writeptr++; /* check end of fifo */ if (fifoCtrl[handle].writeptr > fifoCtrl[handle].endptr) { /* set write pointer to start of the cyclic fifo */ fifoCtrl[handle].writeptr = fifoCtrl[handle].startptr; } /* still here so all is okay */ return BLT_TRUE; } /*** end of UsbFifoMgrWrite ***/
/**************************************************************************************** ** NAME: Init ** PARAMETER: none ** RETURN VALUE: none ** DESCRIPTION: Initializes the microcontroller. The interrupts are disabled, the ** clocks are configured and the flash wait states are configured. ** ****************************************************************************************/ static void Init(void) { volatile blt_int32u StartUpCounter = 0, HSEStatus = 0; blt_int32u pll_multiplier; /* reset the RCC clock configuration to the default reset state (for debug purpose) */ /* set HSION bit */ RCC->CR |= (blt_int32u)0x00000001; /* reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ RCC->CFGR &= (blt_int32u)0xF8FF0000; /* reset HSEON, CSSON and PLLON bits */ RCC->CR &= (blt_int32u)0xFEF6FFFF; /* reset HSEBYP bit */ RCC->CR &= (blt_int32u)0xFFFBFFFF; /* reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (blt_int32u)0xFF80FFFF; /* disable all interrupts and clear pending bits */ RCC->CIR = 0x009F0000; /* enable HSE */ RCC->CR |= ((blt_int32u)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 != 1500)); /* check if time out was reached */ if ((RCC->CR & RCC_CR_HSERDY) == RESET) { /* cannot continue when HSE is not ready */ ASSERT_RT(BLT_FALSE); } /* enable flash prefetch buffer */ FLASH->ACR |= FLASH_ACR_PRFTBE; /* reset flash wait state configuration to default 0 wait states */ FLASH->ACR &= (blt_int32u)((blt_int32u)~FLASH_ACR_LATENCY); #if (BOOT_CPU_SYSTEM_SPEED_KHZ > 48000) /* configure 2 flash wait states */ FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_2; #elif (BOOT_CPU_SYSTEM_SPEED_KHZ > 24000) /* configure 1 flash wait states */ FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_1; #endif /* HCLK = SYSCLK */ RCC->CFGR |= (blt_int32u)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK/2 */ RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK/2 */ RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE1_DIV2; /* reset PLL configuration */ RCC->CFGR &= (blt_int32u)((blt_int32u)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | \ RCC_CFGR_PLLMULL)); /* assert that the pll_multiplier is between 2 and 16 */ ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) >= 2); ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) <= 16); /* calculate multiplier value */ pll_multiplier = BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ; /* convert to register value */ pll_multiplier = (blt_int32u)((pll_multiplier - 2) << 18); /* set the PLL multiplier and clock source */ RCC->CFGR |= (blt_int32u)(RCC_CFGR_PLLSRC_HSE | pll_multiplier); /* 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 &= (blt_int32u)((blt_int32u)~(RCC_CFGR_SW)); RCC->CFGR |= (blt_int32u)RCC_CFGR_SW_PLL; /* wait till PLL is used as system clock source */ while ((RCC->CFGR & (blt_int32u)RCC_CFGR_SWS) != (blt_int32u)0x08) { } /* enable clocks for CAN transmitter and receiver pins (GPIOB and AFIO) */ RCC->APB2ENR |= (blt_int32u)(0x00000008 | 0x00000001); /* configure CAN Rx (GPIOB8) as alternate function input pull-up */ /* first reset the configuration */ GPIOB->CRH &= ~(blt_int32u)((blt_int32u)0xf << 0); /* CNF8[1:0] = %10 and MODE8[1:0] = %00 */ GPIOB->CRH |= (blt_int32u)((blt_int32u)0x8 << 0); /* configure CAN Tx (GPIOB9) as alternate function push-pull */ /* first reset the configuration */ GPIOB->CRH &= ~(blt_int32u)((blt_int32u)0xf << 4); /* CNF9[1:0] = %10 and MODE9[1:0] = %11 */ GPIOB->CRH |= (blt_int32u)((blt_int32u)0xb << 4); /* remap CAN1 pins to PortB */ AFIO->MAPR &= ~(blt_int32u)((blt_int32u)0x3 << 13); AFIO->MAPR |= (blt_int32u)((blt_int32u)0x2 << 13); /* enable clocks for CAN controller peripheral */ RCC->APB1ENR |= (blt_int32u)0x02000000; } /*** end of Init ***/
/************************************************************************************//** ** \brief Catch-all for unused interrrupt service routines. ** \return none. ** ****************************************************************************************/ void UnusedISR(void) { /* unexpected interrupt occured, so trigger an assertion to halt the system */ ASSERT_RT(BLT_FALSE); } /*** end of UnusedISR ***/
/************************************************************************************//** ** \brief Initializes the microcontroller. ** \return none. ** ****************************************************************************************/ static void Init(void) { volatile blt_int32u StartUpCounter = 0, HSEStatus = 0; blt_int32u pll_multiplier; #if (BOOT_FILE_LOGGING_ENABLE > 0) && (BOOT_COM_UART_ENABLE == 0) GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; #endif /* reset the RCC clock configuration to the default reset state (for debug purpose) */ /* set HSION bit */ RCC->CR |= (blt_int32u)0x00000001; /* reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ RCC->CFGR &= (blt_int32u)0xF8FF0000; /* reset HSEON, CSSON and PLLON bits */ RCC->CR &= (blt_int32u)0xFEF6FFFF; /* reset HSEBYP bit */ RCC->CR &= (blt_int32u)0xFFFBFFFF; /* reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (blt_int32u)0xFF80FFFF; /* disable all interrupts and clear pending bits */ RCC->CIR = 0x009F0000; /* enable HSE */ RCC->CR |= ((blt_int32u)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 != 1500)); /* check if time out was reached */ if ((RCC->CR & RCC_CR_HSERDY) == RESET) { /* cannot continue when HSE is not ready */ ASSERT_RT(BLT_FALSE); } /* enable flash prefetch buffer */ FLASH->ACR |= FLASH_ACR_PRFTBE; /* reset flash wait state configuration to default 0 wait states */ FLASH->ACR &= (blt_int32u)((blt_int32u)~FLASH_ACR_LATENCY); #if (BOOT_CPU_SYSTEM_SPEED_KHZ > 48000) /* configure 2 flash wait states */ FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_2; #elif (BOOT_CPU_SYSTEM_SPEED_KHZ > 24000) /* configure 1 flash wait states */ FLASH->ACR |= (blt_int32u)FLASH_ACR_LATENCY_1; #endif /* HCLK = SYSCLK */ RCC->CFGR |= (blt_int32u)RCC_CFGR_HPRE_DIV1; /* PCLK2 = HCLK/2 */ RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK/2 */ RCC->CFGR |= (blt_int32u)RCC_CFGR_PPRE1_DIV2; /* reset PLL configuration */ RCC->CFGR &= (blt_int32u)((blt_int32u)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | \ RCC_CFGR_PLLMULL)); /* assert that the pll_multiplier is between 2 and 16 */ ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) >= 2); ASSERT_CT((BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ) <= 16); /* calculate multiplier value */ pll_multiplier = BOOT_CPU_SYSTEM_SPEED_KHZ/BOOT_CPU_XTAL_SPEED_KHZ; /* convert to register value */ pll_multiplier = (blt_int32u)((pll_multiplier - 2) << 18); /* set the PLL multiplier and clock source */ RCC->CFGR |= (blt_int32u)(RCC_CFGR_PLLSRC_HSE | pll_multiplier); /* 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 &= (blt_int32u)((blt_int32u)~(RCC_CFGR_SW)); RCC->CFGR |= (blt_int32u)RCC_CFGR_SW_PLL; /* wait till PLL is used as system clock source */ while ((RCC->CFGR & (blt_int32u)RCC_CFGR_SWS) != (blt_int32u)0x08) { } #if (BOOT_COM_CAN_ENABLE > 0) /* enable clocks for CAN transmitter and receiver pins (GPIOB and AFIO) */ RCC->APB2ENR |= (blt_int32u)(0x00000008 | 0x00000001); /* configure CAN Rx (GPIOB8) as alternate function input pull-up */ /* first reset the configuration */ GPIOB->CRH &= ~(blt_int32u)((blt_int32u)0xf << 0); /* CNF8[1:0] = %10 and MODE8[1:0] = %00 */ GPIOB->CRH |= (blt_int32u)((blt_int32u)0x8 << 0); /* configure CAN Tx (GPIOB9) as alternate function push-pull */ /* first reset the configuration */ GPIOB->CRH &= ~(blt_int32u)((blt_int32u)0xf << 4); /* CNF9[1:0] = %10 and MODE9[1:0] = %11 */ GPIOB->CRH |= (blt_int32u)((blt_int32u)0xb << 4); /* remap CAN1 pins to PortB */ AFIO->MAPR &= ~(blt_int32u)((blt_int32u)0x3 << 13); AFIO->MAPR |= (blt_int32u)((blt_int32u)0x2 << 13); /* enable clocks for CAN controller peripheral */ RCC->APB1ENR |= (blt_int32u)0x02000000; #endif #if (BOOT_COM_UART_ENABLE > 0) /* enable clock for USART2 peripheral */ RCC->APB1ENR |= (blt_int32u)0x00020000; /* enable clocks for USART2 transmitter and receiver pins (GPIOA and AFIO) */ RCC->APB2ENR |= (blt_int32u)(0x00000004 | 0x00000001); /* configure USART2 Tx (GPIOA2) as alternate function push-pull */ /* first reset the configuration */ GPIOA->CRL &= ~(blt_int32u)((blt_int32u)0xf << 8); /* CNF2[1:0] = %10 and MODE2[1:0] = %11 */ GPIOA->CRL |= (blt_int32u)((blt_int32u)0xb << 8); /* configure USART2 Rx (GPIOA3) as alternate function input floating */ /* first reset the configuration */ GPIOA->CRL &= ~(blt_int32u)((blt_int32u)0xf << 12); /* CNF2[1:0] = %01 and MODE2[1:0] = %00 */ GPIOA->CRL |= (blt_int32u)((blt_int32u)0x4 << 12); #elif (BOOT_FILE_LOGGING_ENABLE > 0) /* enable UART peripheral clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* enable GPIO peripheral clock for transmitter and receiver pins */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); /* configure USART Tx as alternate function push-pull */ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); /* Configure USART Rx as alternate function input floating */ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOA, &GPIO_InitStruct); /* configure UART communcation parameters */ USART_InitStruct.USART_BaudRate = BOOT_COM_UART_BAUDRATE; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStruct); /* enable UART */ USART_Cmd(USART2, ENABLE); #endif } /*** end of Init ***/