2024-06-04 12:45 AM
The motive is to upgrade the firmware of STM32L031xx using the system bootloader. I am facing 2 issues majorly.
1. For this I need to go to boot mode and boot from system memory as per my understanding. STM32L031K6T6 is follows pattern 2 for which there are only 2 requirements to boot from system memory – BOOT0 pin must be pulled up and nBOOT1 bit must be set.
Boot0 is pulled up in hardware and I am setting the nBOOT1 pin in firmware. Once it’s done and we reset the microcontroller, the target is not available anymore (I am flashing and debugging using ST Link Debugger).
Is this an expected behavior? How can I verify if the STM has booted from System Memory? This is the code snippet I am using to Jump to Bootloader section.
void JumpToBootloader(void)
{
HAL_SuspendTick();
/* Clear Interrupt Enable Register & Interrupt Pending Register */
// for (int i=0;i<5;i++)
// {
// NVIC->ICER[i]=0xFFFFFFFF;
// NVIC->ICPR[i]=0xFFFFFFFF;
// }
HAL_NVIC_ClearPendingIRQ(SPI1_IRQn);
HAL_NVIC_DisableIRQ(SPI1_IRQn);
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
SET_BIT(FLASH->OPTR, FLASH_OPTR_BOOT1);
// SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
// while(READ_BIT(FLASH->SR, FLASH_SR_BSY));
HAL_FLASH_OB_Launch();
HAL_GPIO_WritePin(NRST_PORT, NRST_PIN, GPIO_PIN_SET);
}
2. Assuming the above actions enabled the boot up from system memory in STM32L031xx, once I try to send SPI data from swift (in house chip – this is the Master SPI), I don’t get back any acknowledgement from the STM bootloader side. As per AN4286, we need to send the synchronization byte 0x5A, and wait for the acknowledgement byte 0x79.
I never receive the acknowledgement. I am attaching a screenshot of salae logic analyzer.
The code snippet I am using for it.
#define BL_SPI_SOF 0x5AU
#define BL_ACK 0x79U
#define BL_NAK 0x1FU
static void wait_for_ack(void)
{
uint8_t resp;
uint8_t dummy = 0x00U;
uint8_t ack = BL_ACK;
uint32_t ack_received = 0U;
hal_spi_transfer(LPSC_MCU_SPI_NUM, &dummy, NULL, NULL, 1U, 0, 0, LPSC_MCU_GPIO_MASK);
while(ack_received != 1U)
{
hal_spi_transfer(LPSC_MCU_SPI_NUM, &dummy, NULL, &resp, 1U, 0, 1U, LPSC_MCU_GPIO_MASK);
if(resp == BL_ACK)
{
/* Received ACK: send ACK */
hal_spi_transfer(LPSC_MCU_SPI_NUM, &ack, NULL, NULL, 1U, 0, 0, LPSC_MCU_GPIO_MASK);
ack_received = 1U;
}
else if (resp == BL_NAK)
{
/* Received NACK */
Error_Handler();
}
else
{
/* Received junk */
}
}
}
void BL_Init(void)
{
uint8_t sync_byte = BL_SPI_SOF;
/* Send synchronization Byte */
hal_spi_transfer(LPSC_MCU_SPI_NUM, &sync_byte, NULL, NULL, 1U, 0, 0, LPSC_MCU_GPIO_MASK);
/* Get SYNC Byte ACK*/
wait_for_ack();
}
What is missing in the implementation?
Is there more information on the SPI Slave of the System Bootloader, what is the clock polarity and phase set for SPI?
FYI, the SPI communication of the STM32L031xx firmware working as slave is successful with swift, I have verified that. In firmware I have set the Clock Polarity as High and Phase as 2Edge.
Is there any code for firmware upgrade using STM system bootloader available for reference both from master and slave end?
What are the configurations of the GPIOs in system bootloader mode?
2024-06-16 06:33 PM
Since this chip support booting via uart, it's easy to verify the boot from uart using usb to ttl converter. Use CubeProgrammer. It has option to boot via uart. Disconnect all devices connected to other uarts and spi ports to ensure that all false trigger are removed. Once you are sure of the sequence you can boot via spi, remove all uart connections and try