Rename MCU
This commit is contained in:
parent
ed2925a961
commit
64a01bef05
75 changed files with 4 additions and 4 deletions
189
stm32f103t8u6-bootloader/src/usb_com.c
Normal file
189
stm32f103t8u6-bootloader/src/usb_com.c
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
#include "usb_com.h"
|
||||
#include "usb_util.h"
|
||||
#include "commands.h"
|
||||
#include "buildinfo.h"
|
||||
#include "flash.h"
|
||||
|
||||
static const BootloaderInfo_t BootloaderInfo =
|
||||
{
|
||||
.build_date = BUILD_DATE,
|
||||
.build_number = BUILD_NUMBER,
|
||||
.flash_application_start = FLASH_APPLICATION_BASE,
|
||||
.flash_application_size = (FLASH_PAGES - FLASH_BOOTLOADER_PAGES)
|
||||
* FLASH_PAGE_BYTES,
|
||||
.version_major = BUILD_VERSION_MAJOR,
|
||||
.version_minor = BUILD_VERSION_MINOR,
|
||||
.version_patch = BUILD_VERSION_PATCH,
|
||||
.identifier = "STM32F103T8U6"
|
||||
};
|
||||
|
||||
|
||||
static Command_t USB_PendingCommand = CMD_NOP;
|
||||
|
||||
static void USB_EP1Transmit(const void *data, uint16_t length)
|
||||
{
|
||||
USB_MemoryToPMA(USB_BTABLE_ENTRIES[1].ADDR_TX, data, length);
|
||||
USB_BTABLE_ENTRIES[1].COUNT_TX = length;
|
||||
|
||||
// Assume that STAT_TX is currently NAK (which is the case after a reset or
|
||||
// after a correct transfer, just not if the function is called multiple
|
||||
// times without an actual transfer in between)
|
||||
USB->EP1R = (USB_EP_TX_NAK ^ USB_EP_TX_VALID)
|
||||
| USB_EP_CTR_RX | USB_EP_CTR_TX | USB_EPR_EP_TYPE_BULK | 1;
|
||||
}
|
||||
|
||||
bool USB_HandleCommand(const USB_SetupPacket_t *sp)
|
||||
{
|
||||
// The command is stored in the second byte (bRequest field) of the setup
|
||||
// packet
|
||||
Command_t command = sp->bRequest;
|
||||
|
||||
const void *reply_data = NULL;
|
||||
int reply_length = 0;
|
||||
|
||||
switch(command)
|
||||
{
|
||||
case CMD_BOOTLOADER_INFO:
|
||||
reply_data = &BootloaderInfo;
|
||||
reply_length = sizeof(BootloaderInfo)
|
||||
+ strlen(BootloaderInfo.identifier);
|
||||
break;
|
||||
|
||||
case CMD_READ_CRC:
|
||||
// The command will be executed as soon as the start address and
|
||||
// length are transferred via EP2
|
||||
USB_PendingCommand = CMD_READ_CRC;
|
||||
break;
|
||||
|
||||
case CMD_READ_MEMORY:
|
||||
// The command will be executed as soon as the start address and
|
||||
// length are transferred via EP2
|
||||
USB_PendingCommand = CMD_READ_MEMORY;
|
||||
break;
|
||||
|
||||
case CMD_ERASE_PAGE:
|
||||
// The command will be executed as soon as the page number is
|
||||
// transferred via EP2. Since only a single byte is needed for the
|
||||
// page index, this would also be technically be possible with just
|
||||
// one setup packet. Since this is the only command, this minor
|
||||
// USB bandwith saving is not worth the extra special case.
|
||||
USB_PendingCommand = CMD_ERASE_PAGE;
|
||||
break;
|
||||
|
||||
case CMD_PROGRAM:
|
||||
USB_PendingCommand = CMD_PROGRAM;
|
||||
break;
|
||||
|
||||
case CMD_EXIT:
|
||||
return false;
|
||||
|
||||
default:
|
||||
// Invalid commands get ignored
|
||||
break;
|
||||
}
|
||||
|
||||
if(reply_length > 0)
|
||||
{
|
||||
USB_EP1Transmit(reply_data, reply_length);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void USB_HandleEP2Out(void)
|
||||
{
|
||||
// Read how many bytes have been received by EP2
|
||||
int packet_length = USB_BTABLE_ENTRIES[2].COUNT_RX & 0x3ff;
|
||||
|
||||
// The meaning of the received data depends on the command transmitted via
|
||||
// a setup packet before it
|
||||
switch(USB_PendingCommand)
|
||||
{
|
||||
case CMD_READ_CRC:
|
||||
if(packet_length == 8)
|
||||
{
|
||||
uint32_t buff[2];
|
||||
USB_PMAToMemory(buff, USB_BTABLE_ENTRIES[2].ADDR_RX,
|
||||
sizeof(buff));
|
||||
uint32_t *addr = (uint32_t*)(buff[0]);
|
||||
uint32_t length = buff[1];
|
||||
|
||||
CRC->CR = CRC_CR_RESET;
|
||||
|
||||
// TODO: Add basic sanity checks so it isn't possible to crash
|
||||
// the bootloader with this command (or at least not as easy)
|
||||
while(length > 4)
|
||||
{
|
||||
CRC->DR = *addr++;
|
||||
length -= 4;
|
||||
}
|
||||
CRC->DR = *addr & (0xffffffffU >> (32 - 8 * length));
|
||||
|
||||
buff[0] = CRC->DR;
|
||||
USB_EP1Transmit(buff, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_READ_MEMORY:
|
||||
if(packet_length == 8)
|
||||
{
|
||||
uint32_t buff[2];
|
||||
USB_PMAToMemory(buff, USB_BTABLE_ENTRIES[2].ADDR_RX,
|
||||
sizeof(buff));
|
||||
uint8_t *start = (uint8_t*)(buff[0]);
|
||||
uint32_t length = buff[1];
|
||||
|
||||
if(length > 64)
|
||||
{
|
||||
length = 64;
|
||||
}
|
||||
|
||||
USB_EP1Transmit(start, length);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_ERASE_PAGE:
|
||||
if(packet_length == 1)
|
||||
{
|
||||
// Not that only one byte has been received but since the PMA
|
||||
// can only be accessed word-wise, we'll have to copy two
|
||||
uint8_t buff[2];
|
||||
USB_PMAToMemory(buff, USB_BTABLE_ENTRIES[2].ADDR_RX,
|
||||
sizeof(buff));
|
||||
|
||||
unsigned int page_index = buff[0];
|
||||
if(page_index < FLASH_BOOTLOADER_PAGES)
|
||||
{
|
||||
// Do not allow erasing the bootloader
|
||||
buff[0] = FLASH_PROHIBITED;
|
||||
}
|
||||
else
|
||||
{
|
||||
buff[0] = Flash_ErasePage(page_index);
|
||||
}
|
||||
|
||||
// Reply with status byte
|
||||
USB_EP1Transmit(buff, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_PROGRAM:;
|
||||
uint32_t start;
|
||||
USB_PMAToMemory(&start, USB_BTABLE_ENTRIES[2].ADDR_RX, 4);
|
||||
uint32_t length = packet_length - 4;
|
||||
if(start >= FLASH_APPLICATION_BASE && start + length
|
||||
<= FLASH_BASE + FLASH_PAGE_BYTES * FLASH_PAGES)
|
||||
{
|
||||
// Program directly from PMA without an intermediate buffer in
|
||||
// RAM
|
||||
Flash_ProgramFromPMA(start, USB_BTABLE_ENTRIES[2].ADDR_RX + 4,
|
||||
length);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
USB_PendingCommand = CMD_NOP;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue