diff --git a/targets/os/chibios/nanoBooter-cdc/CMakeLists.txt b/targets/os/chibios/nanoBooter-cdc/CMakeLists.txt new file mode 100644 index 0000000000..23463071f0 --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required(VERSION 3.0) +ENABLE_LANGUAGE(ASM) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} +) + +find_package(CHIBIOS REQUIRED) +include_directories(${CHIBIOS_INCLUDE_DIRS}) + + +# pass the RTOS option to the compiler flags +# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CHIBIOS_COMPILE_OPTIONS} ") +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CHIBIOS_COMPILE_OPTIONS} ") + +set(PROJECT_SOURCES + # test app + main.c + usbcfg.c + + # required files to add Wire Protocol + WireProtocol_Receiver.c + WireProtocol_Commands.c +) + +add_executable( + # executables for project, project sources + ${CMAKE_PROJECT_NAME} ${PROJECT_SOURCES} + + # sources for ChibiOS + ${CHIBIOS_SOURCES} + ) + +CHIBIOS_SET_LINKER_OPTIONS(${CMAKE_PROJECT_NAME}) + +CHIBIOS_ADD_HEX_BIN_DUMP_TARGETS(${CMAKE_PROJECT_NAME}) + +CHIBIOS_PRINT_SIZE_OF_TARGETS(${CMAKE_PROJECT_NAME}) + +# generate map file +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.map,--library-path=${PROJECT_BINARY_DIR}/ChibiOS_Source/common/ports/ARMCMx/compilers/GCC,--defsym=__main_stack_size__=0x400,--defsym=__process_stack_size__=0x400") + +set(HEX_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.hex) +set(S19_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.s19) +set(BIN_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.bin) +set(DUMP_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.lst) + +# generate HEX, BIN and LST files as needed +if(CMAKE_BUILD_TYPE EQUAL "Release") + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # copy target image to other formats + COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -Osrec $ ${S19_FILE} + COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${BIN_FILE} + + # copy target file to build folder (this is only usefull for debugging in VS Code because of path in launch.json) + COMMAND ${CMAKE_OBJCOPY} $ ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME} + + COMMENT "Generate HEX and BIN files fro deployment") +else() + add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD + # copy target image to other formats + COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${HEX_FILE} + COMMAND ${CMAKE_OBJCOPY} -Osrec $ ${S19_FILE} + COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${BIN_FILE} + + # copy target file to build folder (this is only usefull for debugging in VS Code because of path in launch.json) + COMMAND ${CMAKE_OBJCOPY} $ ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME} + + # dump target image as source code listing + COMMAND ${CMAKE_OBJDUMP} -d -EL -S $ > ${DUMP_FILE} + COMMENT "Generate HEX and BIN files for deployment, LST file for debug") +endif() diff --git a/targets/os/chibios/nanoBooter-cdc/README.md b/targets/os/chibios/nanoBooter-cdc/README.md new file mode 100644 index 0000000000..fda8c27e90 --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/README.md @@ -0,0 +1,16 @@ +For the ChibiOS test app to build succesfully the following changes are required: + +In _halconf.g_ (when compared with a default file) +- HAL_USE_SERIAL to TRUE +- HAL_USE_SERIAL_USB to TRUE +- HAL_USE_USB to TRUE +- SERIAL_DEFAULT_BITRATE to 115200 + +In _mcuconf.h_ (when compared with a default file) +- STM32_SERIAL_USE_USART2 to TRUE +- STM32_USB_USE_OTG1 to TRUE + +When making the build the first time it will fail with an error about a duplicate definition of __dso_handle. +Edit the file _../various/cpp_wrappers/syscalls_cpp.hpp_ located in the ChibiOS source folder and comment the line where it's being defined there. + +NOTE: this configuration was sucessfully tested in a ST_STM32F4_DISCOVERY board using the Serial over USB connection on USB port 1 that creates a virtual COM port. diff --git a/targets/os/chibios/nanoBooter-cdc/WireProtocol.h b/targets/os/chibios/nanoBooter-cdc/WireProtocol.h new file mode 100644 index 0000000000..5bbe8fee8b --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/WireProtocol.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_H_ +#define _WIREPROTOCOL_H_ + +#include + +#define MARKER_DEBUGGER_V1 "MSdbgV1" // Used to identify the debugger at boot time. +#define MARKER_PACKET_V1 "MSpktV1" // Used to identify the start of a packet. + +struct WP_Packet; +struct WP_Message; + +// enum with Wire Protocol flags +// backwards compatible with .NETMF +typedef enum WP_Flags +{ + WP_Flags_c_NonCritical = 0x0001, // This doesn't need an acknowledge. + WP_Flags_c_Reply = 0x0002, // This is the result of a command. + WP_Flags_c_BadHeader = 0x0004, + WP_Flags_c_BadPayload = 0x0008, + WP_Flags_c_Spare0010 = 0x0010, + WP_Flags_c_Spare0020 = 0x0020, + WP_Flags_c_Spare0040 = 0x0040, + WP_Flags_c_Spare0080 = 0x0080, + WP_Flags_c_Spare0100 = 0x0100, + WP_Flags_c_Spare0200 = 0x0200, + WP_Flags_c_Spare0400 = 0x0400, + WP_Flags_c_Spare0800 = 0x0800, + WP_Flags_c_Spare1000 = 0x1000, + WP_Flags_c_NoCaching = 0x2000, + WP_Flags_c_NACK = 0x4000, + WP_Flags_c_ACK = 0x8000 +}WP_Flags; + +// structure for Wire Protocol packet +// backwards compatible with .NETMF +typedef struct WP_Packet +{ + uint8_t m_signature[8]; + uint32_t m_crcHeader; + uint32_t m_crcData; + + uint32_t m_cmd; + uint16_t m_seq; + uint16_t m_seqReply; + uint32_t m_flags; + uint32_t m_size; +}WP_Packet; + +// structure for Wire Protocol message +// backwards compatible with .NETMF equivalent in names and types to help code reuse +typedef struct WP_Message +{ + WP_Packet m_header; + uint8_t* m_payload; + + uint8_t* m_pos; + uint16_t m_size; + ReceiveState m_rxState; +}WP_Message; + + +// This structure is never used, its purpose is to generate a compiler error in case the size of any structure changes. +struct WP_CompileCheck +{ + char buf1[ sizeof(WP_Packet) == 8 * 4 ? 1 : -1 ]; +}; + +#endif // _WIREPROTOCOL_H_ diff --git a/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.c b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.c new file mode 100644 index 0000000000..88e97030bf --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.c @@ -0,0 +1,57 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + + +#include "WireProtocol_Commands.h" + +// this one is implemented at WireProtocol_Receiver.c +extern void ReplyToCommand(WP_Message* message, bool fSuccess, bool fCritical, void* ptr, int size); + + +bool Monitor_Ping(WP_Message* message) +{ + if((message->m_header.m_flags & WP_Flags_c_Reply) == 0) + { + Monitor_Ping_Reply cmdReply; + // TODO + // set flag with NanoBooter or NanoCLR according to the thread we are running + cmdReply.m_source = Monitor_Ping_c_Ping_Source_NanoBooter; + + ReplyToCommand(message, true, false, &cmdReply, sizeof(cmdReply)); + } + + return true; +} + +bool Monitor_OemInfo(WP_Message* message) +{ + if((message->m_header.m_flags & WP_Flags_c_Reply ) == 0) + { + Monitor_OemInfo_Reply cmdReply; + + bool fOK = NanoBooter_GetReleaseInfo(&cmdReply.m_releaseInfo) == true; + + ReplyToCommand(message, fOK, false, &cmdReply, sizeof(cmdReply) ); + } + + return true; +} + +////////////////////////////////////////////////////////////////////// +// helper functions + +bool NanoBooter_GetReleaseInfo(ReleaseInfo* releaseInfo) +{ + releaseInfo->version.usMajor = 0; + releaseInfo->version.usMinor = 0; + releaseInfo->version.usBuild = 12345; + releaseInfo->version.usRevision = 1; + + // TODO replace this with string from (possibly...) main config file + memcpy(&releaseInfo->infoString, ">>>> nanoFramework RULES <<<<", sizeof(releaseInfo->infoString)); + + return true; +} diff --git a/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.h b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.h new file mode 100644 index 0000000000..1325469f8a --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Commands.h @@ -0,0 +1,101 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_COMMANDS_H_ +#define _WIREPROTOCOL_COMMANDS_H_ + +#include +#include "WireProtocol.h" + +////////////////////////////////////////// +// enums + +// enum with CLR and debugger commands +// backwards compatible with .NETMF +typedef enum CLR_DBG_Commands +{ + CLR_DBG_Commands_c_Monitor_Ping = 0x00000000, // The payload is empty, this command is used to let the other side know we are here... + CLR_DBG_Commands_c_Monitor_Message = 0x00000001, // The payload is composed of the string characters, no zero at the end. + CLR_DBG_Commands_c_Monitor_ReadMemory = 0x00000002, + CLR_DBG_Commands_c_Monitor_WriteMemory = 0x00000003, + CLR_DBG_Commands_c_Monitor_CheckMemory = 0x00000004, + CLR_DBG_Commands_c_Monitor_EraseMemory = 0x00000005, + CLR_DBG_Commands_c_Monitor_Execute = 0x00000006, + CLR_DBG_Commands_c_Monitor_Reboot = 0x00000007, + CLR_DBG_Commands_c_Monitor_MemoryMap = 0x00000008, + CLR_DBG_Commands_c_Monitor_ProgramExit = 0x00000009, // The payload is empty, this command is used to tell the PC of a program termination + CLR_DBG_Commands_c_Monitor_CheckSignature = 0x0000000A, + CLR_DBG_Commands_c_Monitor_DeploymentMap = 0x0000000B, + CLR_DBG_Commands_c_Monitor_FlashSectorMap = 0x0000000C, + CLR_DBG_Commands_c_Monitor_SignatureKeyUpdate = 0x0000000D, + CLR_DBG_Commands_c_Monitor_OemInfo = 0x0000000E, +}CLR_DBG_Commands; + +// enum with flags for Monitor ping source and debugger flags +// backwards compatible with .NETMF in debugger flags only +// adds NEW flags for nanoBooter and nanoCLR +typedef enum Monitor_Ping_Source_Flags +{ + Monitor_Ping_c_Ping_Source_NanoCLR = 0x00010000, + Monitor_Ping_c_Ping_Source_NanoBooter = 0x00010001, + + Monitor_Ping_c_Ping_DbgFlag_Stop = 0x00000001, + Monitor_Ping_c_Ping_DbgFlag_AppExit = 0x00000004, +}Monitor_Ping_Source_Flags; + +////////////////////////////////////////// +// typedefs + +// structure for Monitor Ping Reply +// backwards compatible with .NETMF +typedef struct Monitor_Ping_Reply +{ + uint32_t m_source; + uint32_t m_dbg_flags; + +}Monitor_Ping_Reply; + +// structure to hold 'standard' version information +// equivalent with .NETMF MFVersion +typedef struct VersionInfo +{ + uint16_t usMajor; + uint16_t usMinor; + uint16_t usBuild; + uint16_t usRevision; + +}VersionInfo; + +// structure to hold nano Framework release information +// equivalent with .NETMF MfReleaseInfo +typedef struct ReleaseInfo +{ + + VersionInfo version; + + uint8_t infoString[64-sizeof(VersionInfo)]; + +}ReleaseInfo; + +// structure with reply for OEM information command +typedef struct Monitor_OemInfo_Reply +{ + + ReleaseInfo m_releaseInfo; + +}Monitor_OemInfo_Reply; + +////////////////////////////////////////// +// function declarations (commands) + +bool Monitor_Ping(WP_Message* message); +bool Monitor_OemInfo(WP_Message* message); + +////////////////////////////////////////// +// helper functions +bool NanoBooter_GetReleaseInfo(ReleaseInfo* releaseInfo); + +#endif //_WIREPROTOCOL_COMMANDS_H_ diff --git a/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.c b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.c new file mode 100644 index 0000000000..3f63f9b0fd --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.c @@ -0,0 +1,567 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "WireProtocol_Receiver.h" +#include "usbcfg.h" + +uint8_t receptionBuffer[256]; // was 2048 +uint32_t lastPacketSequence; + + +uint8_t* marker; +WP_Message inboundMessage; +uint16_t lastOutboundMessage; + +//////////////////////////////////////////////////// + +static const CommandHandlerLookup c_Lookup_Request[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping ), + // DEFINE_CMD(Reboot ), + // // + // DEFINE_CMD(ReadMemory ), + // DEFINE_CMD(WriteMemory), + // DEFINE_CMD(CheckMemory), + // DEFINE_CMD(EraseMemory), + // // + // DEFINE_CMD(Execute ), + // DEFINE_CMD(MemoryMap ), + // // + // DEFINE_CMD(CheckSignature), + // // + // DEFINE_CMD(FlashSectorMap ), + // DEFINE_CMD(SignatureKeyUpdate), + + DEFINE_CMD(OemInfo), + +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +//////////////////////////////////////////////////// + +static const CommandHandlerLookup c_Lookup_Reply[] = +{ + /*******************************************************************************************************************************************************************/ +#define DEFINE_CMD(cmd) { CLR_DBG_Commands_c_Monitor_##cmd, &Monitor_##cmd } + DEFINE_CMD(Ping), +#undef DEFINE_CMD + /*******************************************************************************************************************************************************************/ +}; + +//////////////////////////////////////////////////// + +void ReceiverThread(void const * argument) +{ + (void)argument; + + // Initialize to a packet sequence number impossible to encounter + lastPacketSequence = 0x00FEFFFF; + + while (true) { + + // check if there are any data waiting to be read + ////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////// + // change here the check for existing data to be read + ////////////////////////////////////////////////////// + + // only makes sense to check the stream if USB state is active (meaning it's connected to an USB host) + if (SDU1.config->usbp->state == USB_ACTIVE) { + if(!sdGetWouldBlock(&SDU1)) + { + WP_Message_Initialize(&inboundMessage); + WP_Message_PrepareReception(&inboundMessage); + + WP_Message_Process(&inboundMessage); + } + } + + osDelay(500); + } +} + +//////////////////////////////////////////////////// +// WP_Message + +void WP_Message_Initialize(WP_Message* message) +{ + memset(&message->m_header, 0, sizeof(message->m_header)); + message->m_payload = NULL; + message->m_pos = NULL; + message->m_size = 0; + message->m_rxState = ReceiveState_Idle; +} + +void WP_Message_PrepareReception(WP_Message* message) +{ + message->m_rxState = ReceiveState_Initialize; +} + +void WP_Message_PrepareRequest(WP_Message* message, uint32_t cmd, uint32_t flags, uint32_t payloadSize, uint8_t* payload) +{ + memcpy(&message->m_header.m_signature, marker ? marker : (uint8_t*)MARKER_PACKET_V1, sizeof(message->m_header.m_signature)); + + message->m_header.m_crcData = SUPPORT_ComputeCRC(payload, payloadSize, 0); + message->m_header.m_cmd = cmd; + message->m_header.m_seq = lastOutboundMessage++; + message->m_header.m_seqReply = 0; + message->m_header.m_flags = flags; + message->m_header.m_size = payloadSize; + message->m_payload = payload; + + // + // The CRC for the header is computed setting the CRC field to zero and then running the CRC algorithm. + // + message->m_header.m_crcHeader = 0; + message->m_header.m_crcHeader = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); +} + + +void WP_Message_PrepareReply(WP_Message* message, const WP_Packet* req, uint32_t flags, uint32_t payloadSize, uint8_t* payload) +{ + memcpy(&message->m_header.m_signature, marker ? marker : (uint8_t*)MARKER_PACKET_V1, sizeof(message->m_header.m_signature)); + + message->m_header.m_crcData = SUPPORT_ComputeCRC(payload, payloadSize, 0); + message->m_header.m_cmd = req->m_cmd; + message->m_header.m_seq = lastOutboundMessage++; + message->m_header.m_seqReply = req->m_seq; + message->m_header.m_flags = flags | WP_Flags_c_Reply; + message->m_header.m_size = payloadSize; + message->m_payload = payload; + + // + // The CRC for the header is computed setting the CRC field to zero and then running the CRC algorithm. + // + message->m_header.m_crcHeader = 0; + message->m_header.m_crcHeader = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); +} + +void WP_Message_SetPayload(WP_Message* message, uint8_t* payload) +{ + message->m_payload = payload; +} + +void WP_Message_Release(WP_Message* message) +{ + if(message->m_payload) + { + message->m_payload = NULL; + } +} + +bool WP_Message_VerifyHeader(WP_Message* message) +{ + uint32_t crc = message->m_header.m_crcHeader; + message->m_header.m_crcHeader = 0; + uint32_t computedCrc = SUPPORT_ComputeCRC((uint8_t*)&message->m_header, sizeof(message->m_header), 0); + message->m_header.m_crcHeader = crc; + + if(computedCrc != crc) + { + return false; + } + return true; +} + +bool WP_Message_VerifyPayload(WP_Message* message) +{ + if(message->m_payload == NULL && message->m_header.m_size) + { + return false; + } + + uint32_t computedCrc = SUPPORT_ComputeCRC(message->m_payload, message->m_header.m_size, 0); + if(computedCrc != message->m_header.m_crcData) + { + return false; + } + return true; +} + +void WP_Message_ReplyBadPacket(uint32_t flags) +{ + WP_Message message; + WP_Message_Initialize(&message); + WP_Message_PrepareRequest(&message, 0, WP_Flags_c_NonCritical | WP_Flags_c_NACK | flags, 0, NULL); + + SendProtocolMessage(&message); +} + +bool WP_Message_Process(WP_Message* message) +{ + uint8_t* buf = (uint8_t*)&message->m_header; + int len; + + while(true) + { + switch(message->m_rxState) + { + case ReceiveState_Idle: + return true; + + case ReceiveState_Initialize: + WP_Message_Release(message); + + message->m_rxState = ReceiveState_WaitingForHeader; + message->m_pos = (uint8_t*)&message->m_header; + message->m_size = sizeof(message->m_header); + break; + + case ReceiveState_WaitingForHeader: + //TRACE0(TRACE_STATE, "RxState==WaitForHeader\n"); + if(ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + return false; + } + + // Synch to the start of a message. + while(true) + { + len = sizeof(message->m_header) - message->m_size; + if(len <= 0) + { + break; + } + + size_t lenCmp = min(len, sizeof(message->m_header.m_signature)); + + if(memcmp(&message->m_header, MARKER_DEBUGGER_V1, lenCmp) == 0) + { + break; + } + if(memcmp(&message->m_header, MARKER_PACKET_V1, lenCmp) == 0) + { + break; + } + + memmove(&buf[0], &buf[1], len-1); + + message->m_pos--; + message->m_size++; + } + + if(len >= sizeof(message->m_header.m_signature)) + { + message->m_rxState = ReceiveState_ReadingHeader; + } + break; + + case ReceiveState_ReadingHeader: + if(ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + return false; + } + + if(message->m_size == 0) + { + message->m_rxState = ReceiveState_CompleteHeader; + } + break; + + case ReceiveState_CompleteHeader: + { + bool fBadPacket = true; + + if(WP_Message_VerifyHeader(message)) + { + if(ProcessHeader(message)) + { + fBadPacket = false; + + if(message->m_header.m_size) + { + if(message->m_payload == NULL) // Bad, no buffer... + { + message->m_rxState = ReceiveState_Initialize; + } + else + { + // FIXME: m_payloadTicks = HAL_Time_CurrentTicks(); + message->m_rxState = ReceiveState_ReadingPayload; + message->m_pos = message->m_payload; + message->m_size = message->m_header.m_size; + } + } + else + { + message->m_rxState = ReceiveState_CompletePayload; + } + } + } + + if(fBadPacket) + { + if((message->m_header.m_flags & WP_Flags_c_NonCritical) == 0) + { + WP_Message_ReplyBadPacket(WP_Flags_c_BadHeader); + } + + message->m_rxState = ReceiveState_Initialize; + } + } + break; + + case ReceiveState_ReadingPayload: + { + if(ReceiveBytes(message->m_pos, &message->m_size) == false) + { + // didn't receive the expected amount of bytes, returning false + return false; + } + + if(message->m_size == 0) + { + message->m_rxState = ReceiveState_CompletePayload; + } + } + break; + + case ReceiveState_CompletePayload: + if(WP_Message_VerifyPayload(message) == true) + { + ProcessPayload(message); + } + else + { + WP_Message_ReplyBadPacket(WP_Flags_c_BadPayload); + } + + message->m_rxState = ReceiveState_Initialize; + break; + + default: + // unknow state + return false; + } + } +} + +////////////////////////////////////////// +// helper functions + +bool ProcessHeader(WP_Message* message) +{ + // check for reception buffer overflow + if(message->m_header.m_size > sizeof(receptionBuffer)) + { + return false; + } + + message->m_payload = receptionBuffer; + return true; +} + +bool ProcessPayload(WP_Message* message) +{ + // Prevent processing duplicate packets + if(message->m_header.m_seq == lastPacketSequence) + { + return false; // Do not even respond to a repeat packet + } + + // save this packet sequence number + lastPacketSequence = message->m_header.m_seq; + + if(message->m_header.m_flags & WP_Flags_c_NACK) + { + // + // Bad packet... + // + return true; + } + + // TODO + //LOADER_ENGINE_SETFLAG( this, c_LoaderEngineFlag_ValidConnection ); + + size_t num; + const CommandHandlerLookup* cmd; + + if(message->m_header.m_flags & WP_Flags_c_Reply) + { + num = ARRAYSIZE(c_Lookup_Reply); + cmd = c_Lookup_Reply; + } + else + { + num = ARRAYSIZE(c_Lookup_Request); + cmd = c_Lookup_Request; + } + + while(num--) + { + if(cmd->command == message->m_header.m_cmd) + { + // execute commadn handler and save the result + bool commandHandlerExecuteResult = ((bool* (*)(WP_Message*))cmd->handler)(message); + + ReplyToCommand(message, commandHandlerExecuteResult, false, NULL, 0); + return true; + } + + cmd++; + } + + ReplyToCommand(message, false, false, NULL, 0); + + return true; +} + +void ReplyToCommand(WP_Message* message, bool fSuccess, bool fCritical, void* ptr, int size) +{ + WP_Message msgReply; + uint32_t flags = 0; + + // + // Make sure we reply only once! + // + if(message->m_header.m_flags & WP_Flags_c_NonCritical) return; + message->m_header.m_flags |= WP_Flags_c_NonCritical; + + // + // No caching in the request, no caching in the reply... + // + if(message->m_header.m_flags & WP_Flags_c_NoCaching) flags |= WP_Flags_c_NoCaching; + + if(fSuccess ) flags |= WP_Flags_c_ACK; + else flags |= WP_Flags_c_NACK; + if(!fCritical) flags |= WP_Flags_c_NonCritical; + + if(fSuccess == false) + { + ptr = NULL; + size = 0; + } + + WP_Message_Initialize(&msgReply); + + WP_Message_PrepareReply(&msgReply, &message->m_header, flags, size, (uint8_t*)ptr ); + + SendProtocolMessage(&msgReply); +} + +bool SendProtocolMessage(WP_Message* message) +{ + return TransmitMessage(message); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +// These two functions bellow are the ones that need to be ported to new channels when required + +bool ReceiveBytes(uint8_t* ptr, uint16_t* size) +{ + // save for latter comparison + uint16_t requestedSize = *size; + + // sanity check for request of 0 size + if(*size) + { + ////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + ////////////////////////////////////////////////////////// + // change here to read (size) bytes from the input stream + // preferably with read timeout and being able to check + // if the requested number of bytes was actually read + ////////////////////////////////////////////////////////// + + // read from serial stream + volatile size_t read = chSequentialStreamRead((BaseSequentialStream *)&SDU1, ptr, *size); + + ptr += read; + *size -= read; + + // check if the requested read matches the actual read count + return (requestedSize == read); + } + + return true; +} + +bool TransmitMessage(WP_Message* message) +{ + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // change here to write (size) bytes to the output stream + // preferably with timeout and being able to check + // if the write was sucessfull or at least buffered + ////////////////////////////////////////////////////////// + + // write header to output stream + if(chSequentialStreamWrite((BaseSequentialStream *)&SDU1, (const uint8_t *)&message->m_header, sizeof(message->m_header)) != sizeof(message->m_header)) return false; + + // if there is anything on the payload send it to the output stream + if(message->m_header.m_size && message->m_payload) + { + /////////////////////////////////////////////////////////// + // PORTING CHANGE REQUIRED HERE // + /////////////////////////////////////////////////////////// + // see description above + ////////////////////////////////////////////////////////// + if(chSequentialStreamWrite((BaseSequentialStream *)&SDU1, message->m_payload, message->m_header.m_size ) != message->m_header.m_size) return false; + } + + return true; +} +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// CRC 32 table for use under ZModem protocol, IEEE 802 +// G(x) = x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1 +static const uint32_t c_CRCTable[256] = +{ + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 +}; + +uint32_t SUPPORT_ComputeCRC(const void* rgBlock, int nLength, uint32_t crc) +{ + const uint8_t* ptr = (const uint8_t*)rgBlock; + + while(nLength-- > 0) + { + crc = c_CRCTable[((crc >> 24) ^ (*ptr++)) & 0xFF] ^ (crc << 8); + } + + return crc; +} diff --git a/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.h b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.h new file mode 100644 index 0000000000..eb440d07b5 --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/WireProtocol_Receiver.h @@ -0,0 +1,75 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#ifndef _WIREPROTOCOL_RECEIVER_H_ +#define _WIREPROTOCOL_RECEIVER_H_ + +#include +#include +#include + +#include "WireProtocol.h" +#include "WireProtocol_Commands.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) +#endif + +// enum with machine states for Wire Procotol receiver +typedef enum ReceiveState +{ + ReceiveState_Idle = (1 << 0), + ReceiveState_Initialize = (2 << 0), + ReceiveState_WaitingForHeader = (3 << 0), + ReceiveState_ReadingHeader = (4 << 0), + ReceiveState_CompleteHeader = (5 << 0), + ReceiveState_ReadingPayload = (6 << 0), + ReceiveState_CompletePayload = (7 << 0), +}ReceiveState; + +// structure for Wire Protocol command handler lookup +typedef struct CommandHandlerLookup +{ + uint32_t command; + + void* handler; + +}CommandHandlerLookup; + +//////////////////////////////////////////////////// +// function declarations (related with WP_Message) + +void WP_Message_Initialize(WP_Message* message); +void WP_Message_PrepareReception(WP_Message* message); +void WP_Message_PrepareRequest(WP_Message* message, uint32_t cmd, uint32_t flags, uint32_t payloadSize, uint8_t* payload); +void WP_Message_PrepareReply(WP_Message* message, const WP_Packet* req, uint32_t flags, uint32_t payloadSize, uint8_t* payload); +void WP_Message_SetPayload(WP_Message* message, uint8_t* payload); +void WP_Message_Release(WP_Message* message); +bool WP_Message_VerifyHeader(WP_Message* message); +bool WP_Message_VerifyPayload(WP_Message* message); +void WP_Message_ReplyBadPacket(uint32_t flags); +bool WP_Message_Process(WP_Message* message); +bool ReceiveBytes(uint8_t* ptr, uint16_t* size); + +////////////////////////////////////////// +// helper functions +void ReplyToCommand(WP_Message* message, bool fSuccess, bool fCritical, void* ptr, int size); +bool SendProtocolMessage(WP_Message* message); +bool TransmitMessage(WP_Message* message); +bool ProcessHeader(WP_Message* message); +bool ProcessPayload(WP_Message* message); + +uint32_t SUPPORT_ComputeCRC(const void* rgBlock, int nLength, uint32_t crc); + +////////////////////////////////////////// +// functions with RTOS stuff +void ReceiverThread(void const * argument); + +#endif // _WIREPROTOCOL_RECEIVER_H_ diff --git a/targets/os/chibios/nanoBooter-cdc/chconf.h b/targets/os/chibios/nanoBooter-cdc/chconf.h new file mode 100644 index 0000000000..f7e1514137 --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/chconf.h @@ -0,0 +1,500 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef _CHCONF_H_ +#define _CHCONF_H_ + +#define CORTEX_USE_FPU FALSE +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY FALSE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief I/O Queues APIs. + * @details If enabled then the I/O queues APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_QUEUES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the context switch circular trace buffer is + * activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_TRACE FALSE + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK FALSE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + * + * @note It is inserted into lock zone. + * @note It is also invoked when the threads simply return in order to + * terminate. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* _CHCONF_H_ */ + +/** @} */ diff --git a/targets/os/chibios/nanoBooter-cdc/halconf.h b/targets/os/chibios/nanoBooter-cdc/halconf.h new file mode 100644 index 0000000000..169ead85ba --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/halconf.h @@ -0,0 +1,381 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef _HALCONF_H_ +#define _HALCONF_H_ + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC FALSE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT FALSE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL TRUE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 115200 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT FALSE +#endif + +#endif /* _HALCONF_H_ */ + +/** @} */ diff --git a/targets/os/chibios/nanoBooter-cdc/main.c b/targets/os/chibios/nanoBooter-cdc/main.c new file mode 100644 index 0000000000..2f564941bc --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/main.c @@ -0,0 +1,79 @@ +// +// Copyright (c) 2017 The nano Framework project contributors +// See LICENSE file in the project root for full license information. +// + +#include +#include +#include + +#include "usbcfg.h" +#include "WireProtocol_Receiver.h" + +void BlinkerThread(void const * argument) +{ + (void)argument; + + while (true) { + palSetPad(GPIOD, GPIOD_LED3); + osDelay(250); + + palClearPad(GPIOD, GPIOD_LED3); + palSetPad(GPIOD, GPIOD_LED5); + osDelay(250); + + palClearPad(GPIOD, GPIOD_LED5); + palSetPad(GPIOD, GPIOD_LED6); + osDelay(250); + + palClearPad(GPIOD, GPIOD_LED6); + palSetPad(GPIOD, GPIOD_LED4); + osDelay(250); + + palClearPad(GPIOD, GPIOD_LED4); + } +} +osThreadDef(BlinkerThread, osPriorityNormal, 128); + +// need to declare the Receiver thread here +osThreadDef(ReceiverThread, osPriorityNormal, 1024); + +// Application entry point. +int main(void) { + + // HAL initialization, this also initializes the configured device drivers + // and performs the board-specific initializations. + halInit(); + + // The kernel is initialized but not started yet, this means that + // main() is executing with absolute priority but interrupts are + // already enabled. + osKernelInitialize(); + + // Initializes a serial-over-USB CDC driver. + sduObjectInit(&SDU1); + sduStart(&SDU1, &serusbcfg); + + // Activates the USB driver and then the USB bus pull-up on D+. + // Note, a delay is inserted in order to not have to disconnect the cable + // after a reset. + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + + // Creates the blinker thread, it does not start immediately. + osThreadCreate(osThread(BlinkerThread), NULL); + + // create the receiver thread + osThreadCreate(osThread(ReceiverThread), NULL); + + // Kernel started, the main() thread has priority osPriorityNormal + // by default. + osKernelStart(); + + // Normal main() thread activity it does nothing except sleeping in a loop + while (true) { + osDelay(1000); + } +} diff --git a/targets/os/chibios/nanoBooter-cdc/mcuconf.h b/targets/os/chibios/nanoBooter-cdc/mcuconf.h new file mode 100644 index 0000000000..f3407a1771 --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/mcuconf.h @@ -0,0 +1,342 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _MCUCONF_H_ +#define _MCUCONF_H_ + +/* + * STM32F4xx drivers configuration. + * The following settings override the default settings present in + * the various device driver implementation headers. + * Note that the settings for each driver only have effect if the whole + * driver is enabled in halconf.h. + * + * IRQ priorities: + * 15...0 Lowest...Highest. + * + * DMA priorities: + * 0...3 Lowest...Highest. + */ + +#define STM32F4xx_MCUCONF + +/* + * HAL driver system settings. + */ +#define STM32_NO_INIT FALSE +#define STM32_HSI_ENABLED TRUE +#define STM32_LSI_ENABLED TRUE +#define STM32_HSE_ENABLED TRUE +#define STM32_LSE_ENABLED FALSE +#define STM32_CLOCK48_REQUIRED TRUE +#define STM32_SW STM32_SW_PLL +#define STM32_PLLSRC STM32_PLLSRC_HSE +#define STM32_PLLM_VALUE 8 +#define STM32_PLLN_VALUE 336 +#define STM32_PLLP_VALUE 2 +#define STM32_PLLQ_VALUE 7 +#define STM32_HPRE STM32_HPRE_DIV1 +#define STM32_PPRE1 STM32_PPRE1_DIV4 +#define STM32_PPRE2 STM32_PPRE2_DIV2 +#define STM32_RTCSEL STM32_RTCSEL_LSI +#define STM32_RTCPRE_VALUE 8 +#define STM32_MCO1SEL STM32_MCO1SEL_HSI +#define STM32_MCO1PRE STM32_MCO1PRE_DIV1 +#define STM32_MCO2SEL STM32_MCO2SEL_SYSCLK +#define STM32_MCO2PRE STM32_MCO2PRE_DIV5 +#define STM32_I2SSRC STM32_I2SSRC_CKIN +#define STM32_PLLI2SN_VALUE 192 +#define STM32_PLLI2SR_VALUE 5 +#define STM32_PVD_ENABLE FALSE +#define STM32_PLS STM32_PLS_LEV0 +#define STM32_BKPRAM_ENABLE FALSE + +/* + * ADC driver system settings. + */ +#define STM32_ADC_ADCPRE ADC_CCR_ADCPRE_DIV4 +#define STM32_ADC_USE_ADC1 FALSE +#define STM32_ADC_USE_ADC2 FALSE +#define STM32_ADC_USE_ADC3 FALSE +#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(2, 4) +#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 1) +#define STM32_ADC_ADC1_DMA_PRIORITY 2 +#define STM32_ADC_ADC2_DMA_PRIORITY 2 +#define STM32_ADC_ADC3_DMA_PRIORITY 2 +#define STM32_ADC_IRQ_PRIORITY 6 +#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 6 +#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 6 + +/* + * CAN driver system settings. + */ +#define STM32_CAN_USE_CAN1 FALSE +#define STM32_CAN_USE_CAN2 FALSE +#define STM32_CAN_CAN1_IRQ_PRIORITY 11 +#define STM32_CAN_CAN2_IRQ_PRIORITY 11 + +/* + * DAC driver system settings. + */ +#define STM32_DAC_DUAL_MODE FALSE +#define STM32_DAC_USE_DAC1_CH1 FALSE +#define STM32_DAC_USE_DAC1_CH2 FALSE +#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10 +#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2 +#define STM32_DAC_DAC1_CH1_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_DAC_DAC1_CH2_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) + +/* + * EXT driver system settings. + */ +#define STM32_EXT_EXTI0_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI1_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI2_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI3_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI4_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI16_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI17_IRQ_PRIORITY 15 +#define STM32_EXT_EXTI18_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI19_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI20_IRQ_PRIORITY 6 +#define STM32_EXT_EXTI21_IRQ_PRIORITY 15 +#define STM32_EXT_EXTI22_IRQ_PRIORITY 15 + +/* + * GPT driver system settings. + */ +#define STM32_GPT_USE_TIM1 FALSE +#define STM32_GPT_USE_TIM2 FALSE +#define STM32_GPT_USE_TIM3 FALSE +#define STM32_GPT_USE_TIM4 FALSE +#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM6 FALSE +#define STM32_GPT_USE_TIM7 FALSE +#define STM32_GPT_USE_TIM8 FALSE +#define STM32_GPT_USE_TIM9 FALSE +#define STM32_GPT_USE_TIM11 FALSE +#define STM32_GPT_USE_TIM12 FALSE +#define STM32_GPT_USE_TIM14 FALSE +#define STM32_GPT_TIM1_IRQ_PRIORITY 7 +#define STM32_GPT_TIM2_IRQ_PRIORITY 7 +#define STM32_GPT_TIM3_IRQ_PRIORITY 7 +#define STM32_GPT_TIM4_IRQ_PRIORITY 7 +#define STM32_GPT_TIM5_IRQ_PRIORITY 7 +#define STM32_GPT_TIM6_IRQ_PRIORITY 7 +#define STM32_GPT_TIM7_IRQ_PRIORITY 7 +#define STM32_GPT_TIM8_IRQ_PRIORITY 7 +#define STM32_GPT_TIM9_IRQ_PRIORITY 7 +#define STM32_GPT_TIM11_IRQ_PRIORITY 7 +#define STM32_GPT_TIM12_IRQ_PRIORITY 7 +#define STM32_GPT_TIM14_IRQ_PRIORITY 7 + +/* + * I2C driver system settings. + */ +#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C2 FALSE +#define STM32_I2C_USE_I2C3 FALSE +#define STM32_I2C_BUSY_TIMEOUT 50 +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2C_I2C1_IRQ_PRIORITY 5 +#define STM32_I2C_I2C2_IRQ_PRIORITY 5 +#define STM32_I2C_I2C3_IRQ_PRIORITY 5 +#define STM32_I2C_I2C1_DMA_PRIORITY 3 +#define STM32_I2C_I2C2_DMA_PRIORITY 3 +#define STM32_I2C_I2C3_DMA_PRIORITY 3 +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") + +/* + * I2S driver system settings. + */ +#define STM32_I2S_USE_SPI2 FALSE +#define STM32_I2S_USE_SPI3 FALSE +#define STM32_I2S_SPI2_IRQ_PRIORITY 10 +#define STM32_I2S_SPI3_IRQ_PRIORITY 10 +#define STM32_I2S_SPI2_DMA_PRIORITY 1 +#define STM32_I2S_SPI3_DMA_PRIORITY 1 +#define STM32_I2S_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_I2S_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_I2S_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_I2S_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2S_DMA_ERROR_HOOK(i2sp) osalSysHalt("DMA failure") + +/* + * ICU driver system settings. + */ +#define STM32_ICU_USE_TIM1 FALSE +#define STM32_ICU_USE_TIM2 FALSE +#define STM32_ICU_USE_TIM3 FALSE +#define STM32_ICU_USE_TIM4 FALSE +#define STM32_ICU_USE_TIM5 FALSE +#define STM32_ICU_USE_TIM8 FALSE +#define STM32_ICU_USE_TIM9 FALSE +#define STM32_ICU_TIM1_IRQ_PRIORITY 7 +#define STM32_ICU_TIM2_IRQ_PRIORITY 7 +#define STM32_ICU_TIM3_IRQ_PRIORITY 7 +#define STM32_ICU_TIM4_IRQ_PRIORITY 7 +#define STM32_ICU_TIM5_IRQ_PRIORITY 7 +#define STM32_ICU_TIM8_IRQ_PRIORITY 7 +#define STM32_ICU_TIM9_IRQ_PRIORITY 7 + +/* + * MAC driver system settings. + */ +#define STM32_MAC_TRANSMIT_BUFFERS 2 +#define STM32_MAC_RECEIVE_BUFFERS 4 +#define STM32_MAC_BUFFERS_SIZE 1522 +#define STM32_MAC_PHY_TIMEOUT 100 +#define STM32_MAC_ETH1_CHANGE_PHY_STATE TRUE +#define STM32_MAC_ETH1_IRQ_PRIORITY 13 +#define STM32_MAC_IP_CHECKSUM_OFFLOAD 0 + +/* + * PWM driver system settings. + */ +#define STM32_PWM_USE_ADVANCED FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE +#define STM32_PWM_USE_TIM4 FALSE +#define STM32_PWM_USE_TIM5 FALSE +#define STM32_PWM_USE_TIM8 FALSE +#define STM32_PWM_USE_TIM9 FALSE +#define STM32_PWM_TIM1_IRQ_PRIORITY 7 +#define STM32_PWM_TIM2_IRQ_PRIORITY 7 +#define STM32_PWM_TIM3_IRQ_PRIORITY 7 +#define STM32_PWM_TIM4_IRQ_PRIORITY 7 +#define STM32_PWM_TIM5_IRQ_PRIORITY 7 +#define STM32_PWM_TIM8_IRQ_PRIORITY 7 +#define STM32_PWM_TIM9_IRQ_PRIORITY 7 + +/* + * SDC driver system settings. + */ +#define STM32_SDC_SDIO_DMA_PRIORITY 3 +#define STM32_SDC_SDIO_IRQ_PRIORITY 9 +#define STM32_SDC_WRITE_TIMEOUT_MS 250 +#define STM32_SDC_READ_TIMEOUT_MS 25 +#define STM32_SDC_CLOCK_ACTIVATION_DELAY 10 +#define STM32_SDC_SDIO_UNALIGNED_SUPPORT TRUE +#define STM32_SDC_SDIO_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) + +/* + * SERIAL driver system settings. + */ +#define STM32_SERIAL_USE_USART1 FALSE +#define STM32_SERIAL_USE_USART2 TRUE +#define STM32_SERIAL_USE_USART3 FALSE +#define STM32_SERIAL_USE_UART4 FALSE +#define STM32_SERIAL_USE_UART5 FALSE +#define STM32_SERIAL_USE_USART6 FALSE +#define STM32_SERIAL_USART1_PRIORITY 12 +#define STM32_SERIAL_USART2_PRIORITY 12 +#define STM32_SERIAL_USART3_PRIORITY 12 +#define STM32_SERIAL_UART4_PRIORITY 12 +#define STM32_SERIAL_UART5_PRIORITY 12 +#define STM32_SERIAL_USART6_PRIORITY 12 + +/* + * SPI driver system settings. + */ +#define STM32_SPI_USE_SPI1 FALSE +#define STM32_SPI_USE_SPI2 FALSE +#define STM32_SPI_USE_SPI3 FALSE +#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) +#define STM32_SPI_SPI1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 3) +#define STM32_SPI_SPI2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_SPI_SPI2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_SPI_SPI3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_SPI_SPI3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") + +/* + * ST driver system settings. + */ +#define STM32_ST_IRQ_PRIORITY 8 +#define STM32_ST_USE_TIMER 2 + +/* + * UART driver system settings. + */ +#define STM32_UART_USE_USART1 FALSE +#define STM32_UART_USE_USART2 FALSE +#define STM32_UART_USE_USART3 FALSE +#define STM32_UART_USE_UART4 FALSE +#define STM32_UART_USE_UART5 FALSE +#define STM32_UART_USE_USART6 FALSE +#define STM32_UART_USART1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 5) +#define STM32_UART_USART1_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_UART_USART2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_UART_USART3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 1) +#define STM32_UART_USART3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 3) +#define STM32_UART_UART4_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#define STM32_UART_UART4_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#define STM32_UART_UART5_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#define STM32_UART_UART5_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_UART_USART6_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 2) +#define STM32_UART_USART6_TX_DMA_STREAM STM32_DMA_STREAM_ID(2, 7) +#define STM32_UART_USART1_IRQ_PRIORITY 12 +#define STM32_UART_USART2_IRQ_PRIORITY 12 +#define STM32_UART_USART3_IRQ_PRIORITY 12 +#define STM32_UART_UART4_IRQ_PRIORITY 12 +#define STM32_UART_UART5_IRQ_PRIORITY 12 +#define STM32_UART_USART6_IRQ_PRIORITY 12 +#define STM32_UART_USART1_DMA_PRIORITY 0 +#define STM32_UART_USART2_DMA_PRIORITY 0 +#define STM32_UART_USART3_DMA_PRIORITY 0 +#define STM32_UART_UART4_DMA_PRIORITY 0 +#define STM32_UART_UART5_DMA_PRIORITY 0 +#define STM32_UART_USART6_DMA_PRIORITY 0 +#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure") + +/* + * USB driver system settings. + */ +#define STM32_USB_USE_OTG1 TRUE +#define STM32_USB_USE_OTG2 FALSE +#define STM32_USB_OTG1_IRQ_PRIORITY 14 +#define STM32_USB_OTG2_IRQ_PRIORITY 14 +#define STM32_USB_OTG1_RX_FIFO_SIZE 512 +#define STM32_USB_OTG2_RX_FIFO_SIZE 1024 +#define STM32_USB_OTG_THREAD_PRIO LOWPRIO +#define STM32_USB_OTG_THREAD_STACK_SIZE 128 +#define STM32_USB_OTGFIFO_FILL_BASEPRI 0 + +/* + * WDG driver system settings. + */ +#define STM32_WDG_USE_IWDG FALSE + +#endif /* _MCUCONF_H_ */ diff --git a/targets/os/chibios/nanoBooter-cdc/usbcfg.c b/targets/os/chibios/nanoBooter-cdc/usbcfg.c new file mode 100644 index 0000000000..262f3f6f2b --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/usbcfg.c @@ -0,0 +1,336 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +/* Virtual serial port over USB.*/ +SerialUSBDriver SDU1; + +/* + * Endpoints to be used for USBD1. + */ +#define USBD1_DATA_REQUEST_EP 1 +#define USBD1_DATA_AVAILABLE_EP 1 +#define USBD1_INTERRUPT_REQUEST_EP 2 + +/* + * USB Device Descriptor. + */ +static const uint8_t vcom_device_descriptor_data[18] = { + USB_DESC_DEVICE (0x0110, /* bcdUSB (1.1). */ + 0x02, /* bDeviceClass (CDC). */ + 0x00, /* bDeviceSubClass. */ + 0x00, /* bDeviceProtocol. */ + 0x40, /* bMaxPacketSize. */ + 0x0483, /* idVendor (ST). */ + 0x5740, /* idProduct. */ + 0x0200, /* bcdDevice. */ + 1, /* iManufacturer. */ + 2, /* iProduct. */ + 3, /* iSerialNumber. */ + 1) /* bNumConfigurations. */ +}; + +/* + * Device Descriptor wrapper. + */ +static const USBDescriptor vcom_device_descriptor = { + sizeof vcom_device_descriptor_data, + vcom_device_descriptor_data +}; + +/* Configuration Descriptor tree for a CDC.*/ +static const uint8_t vcom_configuration_descriptor_data[67] = { + /* Configuration Descriptor.*/ + USB_DESC_CONFIGURATION(67, /* wTotalLength. */ + 0x02, /* bNumInterfaces. */ + 0x01, /* bConfigurationValue. */ + 0, /* iConfiguration. */ + 0xC0, /* bmAttributes (self powered). */ + 50), /* bMaxPower (100mA). */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x00, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x01, /* bNumEndpoints. */ + 0x02, /* bInterfaceClass (Communications + Interface Class, CDC section + 4.2). */ + 0x02, /* bInterfaceSubClass (Abstract + Control Model, CDC section 4.3). */ + 0x01, /* bInterfaceProtocol (AT commands, + CDC section 4.4). */ + 0), /* iInterface. */ + /* Header Functional Descriptor (CDC section 5.2.3).*/ + USB_DESC_BYTE (5), /* bLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x00), /* bDescriptorSubtype (Header + Functional Descriptor. */ + USB_DESC_BCD (0x0110), /* bcdCDC. */ + /* Call Management Functional Descriptor. */ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x01), /* bDescriptorSubtype (Call Management + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bmCapabilities (D0+D1). */ + USB_DESC_BYTE (0x01), /* bDataInterface. */ + /* ACM Functional Descriptor.*/ + USB_DESC_BYTE (4), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x02), /* bDescriptorSubtype (Abstract + Control Management Descriptor). */ + USB_DESC_BYTE (0x02), /* bmCapabilities. */ + /* Union Functional Descriptor.*/ + USB_DESC_BYTE (5), /* bFunctionLength. */ + USB_DESC_BYTE (0x24), /* bDescriptorType (CS_INTERFACE). */ + USB_DESC_BYTE (0x06), /* bDescriptorSubtype (Union + Functional Descriptor). */ + USB_DESC_BYTE (0x00), /* bMasterInterface (Communication + Class Interface). */ + USB_DESC_BYTE (0x01), /* bSlaveInterface0 (Data Class + Interface). */ + /* Endpoint 2 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_INTERRUPT_REQUEST_EP|0x80, + 0x03, /* bmAttributes (Interrupt). */ + 0x0008, /* wMaxPacketSize. */ + 0xFF), /* bInterval. */ + /* Interface Descriptor.*/ + USB_DESC_INTERFACE (0x01, /* bInterfaceNumber. */ + 0x00, /* bAlternateSetting. */ + 0x02, /* bNumEndpoints. */ + 0x0A, /* bInterfaceClass (Data Class + Interface, CDC section 4.5). */ + 0x00, /* bInterfaceSubClass (CDC section + 4.6). */ + 0x00, /* bInterfaceProtocol (CDC section + 4.7). */ + 0x00), /* iInterface. */ + /* Endpoint 3 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_AVAILABLE_EP, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00), /* bInterval. */ + /* Endpoint 1 Descriptor.*/ + USB_DESC_ENDPOINT (USBD1_DATA_REQUEST_EP|0x80, /* bEndpointAddress.*/ + 0x02, /* bmAttributes (Bulk). */ + 0x0040, /* wMaxPacketSize. */ + 0x00) /* bInterval. */ +}; + +/* + * Configuration Descriptor wrapper. + */ +static const USBDescriptor vcom_configuration_descriptor = { + sizeof vcom_configuration_descriptor_data, + vcom_configuration_descriptor_data +}; + +/* + * U.S. English language identifier. + */ +static const uint8_t vcom_string0[] = { + USB_DESC_BYTE(4), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + USB_DESC_WORD(0x0409) /* wLANGID (U.S. English). */ +}; + +/* + * Vendor string. + */ +static const uint8_t vcom_string1[] = { + USB_DESC_BYTE(38), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + 'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0, + 'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0, + 'c', 0, 's', 0 +}; + +/* + * Device Description string. + */ +static const uint8_t vcom_string2[] = { + USB_DESC_BYTE(56), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + 'C', 0, 'h', 0, 'i', 0, 'b', 0, 'i', 0, 'O', 0, 'S', 0, '/', 0, + 'R', 0, 'T', 0, ' ', 0, 'V', 0, 'i', 0, 'r', 0, 't', 0, 'u', 0, + 'a', 0, 'l', 0, ' ', 0, 'C', 0, 'O', 0, 'M', 0, ' ', 0, 'P', 0, + 'o', 0, 'r', 0, 't', 0 +}; + +/* + * Serial Number string. + */ +static const uint8_t vcom_string3[] = { + USB_DESC_BYTE(8), /* bLength. */ + USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ + '0' + CH_KERNEL_MAJOR, 0, + '0' + CH_KERNEL_MINOR, 0, + '0' + CH_KERNEL_PATCH, 0 +}; + +/* + * Strings wrappers array. + */ +static const USBDescriptor vcom_strings[] = { + {sizeof vcom_string0, vcom_string0}, + {sizeof vcom_string1, vcom_string1}, + {sizeof vcom_string2, vcom_string2}, + {sizeof vcom_string3, vcom_string3} +}; + +/* + * Handles the GET_DESCRIPTOR callback. All required descriptors must be + * handled here. + */ +static const USBDescriptor *get_descriptor(USBDriver *usbp, + uint8_t dtype, + uint8_t dindex, + uint16_t lang) { + + (void)usbp; + (void)lang; + switch (dtype) { + case USB_DESCRIPTOR_DEVICE: + return &vcom_device_descriptor; + case USB_DESCRIPTOR_CONFIGURATION: + return &vcom_configuration_descriptor; + case USB_DESCRIPTOR_STRING: + if (dindex < 4) + return &vcom_strings[dindex]; + } + return NULL; +} + +/** + * @brief IN EP1 state. + */ +static USBInEndpointState ep1instate; + +/** + * @brief OUT EP1 state. + */ +static USBOutEndpointState ep1outstate; + +/** + * @brief EP1 initialization structure (both IN and OUT). + */ +static const USBEndpointConfig ep1config = { + USB_EP_MODE_TYPE_BULK, + NULL, + sduDataTransmitted, + sduDataReceived, + 0x0040, + 0x0040, + &ep1instate, + &ep1outstate, + 2, + NULL +}; + +/** + * @brief IN EP2 state. + */ +static USBInEndpointState ep2instate; + +/** + * @brief EP2 initialization structure (IN only). + */ +static const USBEndpointConfig ep2config = { + USB_EP_MODE_TYPE_INTR, + NULL, + sduInterruptTransmitted, + NULL, + 0x0010, + 0x0000, + &ep2instate, + NULL, + 1, + NULL +}; + +/* + * Handles the USB driver global events. + */ +static void usb_event(USBDriver *usbp, usbevent_t event) { + extern SerialUSBDriver SDU1; + + switch (event) { + case USB_EVENT_RESET: + return; + case USB_EVENT_ADDRESS: + return; + case USB_EVENT_CONFIGURED: + chSysLockFromISR(); + + /* Enables the endpoints specified into the configuration. + Note, this callback is invoked from an ISR so I-Class functions + must be used.*/ + usbInitEndpointI(usbp, USBD1_DATA_REQUEST_EP, &ep1config); + usbInitEndpointI(usbp, USBD1_INTERRUPT_REQUEST_EP, &ep2config); + + /* Resetting the state of the CDC subsystem.*/ + sduConfigureHookI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_UNCONFIGURED: + return; + case USB_EVENT_SUSPEND: + chSysLockFromISR(); + + /* Disconnection event on suspend.*/ + sduDisconnectI(&SDU1); + + chSysUnlockFromISR(); + return; + case USB_EVENT_WAKEUP: + return; + case USB_EVENT_STALLED: + return; + } + return; +} + +/* + * Handles the USB driver global events. + */ +static void sof_handler(USBDriver *usbp) { + + (void)usbp; + + osalSysLockFromISR(); + sduSOFHookI(&SDU1); + osalSysUnlockFromISR(); +} + +/* + * USB driver configuration. + */ +const USBConfig usbcfg = { + usb_event, + get_descriptor, + sduRequestsHook, + sof_handler +}; + +/* + * Serial over USB driver configuration. + */ +const SerialUSBConfig serusbcfg = { + &USBD1, + USBD1_DATA_REQUEST_EP, + USBD1_DATA_AVAILABLE_EP, + USBD1_INTERRUPT_REQUEST_EP +}; diff --git a/targets/os/chibios/nanoBooter-cdc/usbcfg.h b/targets/os/chibios/nanoBooter-cdc/usbcfg.h new file mode 100644 index 0000000000..366ce0c43c --- /dev/null +++ b/targets/os/chibios/nanoBooter-cdc/usbcfg.h @@ -0,0 +1,26 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _USBCFG_H_ +#define _USBCFG_H_ + +extern const USBConfig usbcfg; +extern SerialUSBConfig serusbcfg; +extern SerialUSBDriver SDU1; + +#endif /* _USBCFG_H_ */ + +/** @} */