Merge commit 'be3bfc48a8be7cd4d84709e98c5def13259d49f6' into sam-update
# Conflicts: # README.md
This commit is contained in:
commit
d36213b7d0
35
.travis.yml
35
.travis.yml
@ -1,42 +1,11 @@
|
||||
dist: trusty
|
||||
dist: bionic
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
|
||||
- sudo apt-get update -qq
|
||||
- pip install --user intelhex
|
||||
- gpg --recv-keys 3CEA9B8868BC3852618EB5B4707F91A424F006F5
|
||||
- wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2
|
||||
- wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2.sig
|
||||
- gpg --trust-model always --verify libftdi1-1.2.tar.bz2.sig
|
||||
- tar -xjf libftdi1-1.2.tar.bz2
|
||||
- sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev libhidapi-dev
|
||||
|
||||
install:
|
||||
- cd libftdi1-1.2
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ];
|
||||
then
|
||||
sudo apt-get update -qq;
|
||||
if [ "$ARCH" = "x86_64" ];
|
||||
then
|
||||
sudo apt-get install -qq libusb-1.0-0-dev;
|
||||
elif [ "$ARCH" = "i386" ];
|
||||
then
|
||||
sudo apt-get install -qq gcc-multilib libusb-1.0-0-dev:i386 pkg-config:i386;
|
||||
export CFLAGS="-m32";
|
||||
fi
|
||||
fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ];
|
||||
then
|
||||
brew update;
|
||||
brew install libusb;
|
||||
fi
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ../
|
||||
- make
|
||||
- sudo make install
|
||||
- cd ../../
|
||||
- sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev libhidapi-dev libftdi1 libftdi1-dev
|
||||
|
||||
script:
|
||||
- make -C libopencm3 lib
|
||||
|
@ -62,7 +62,7 @@ SRC = \
|
||||
|
||||
include $(PLATFORM_DIR)/Makefile.inc
|
||||
|
||||
OPT_FLAGS ?= -Og
|
||||
OPT_FLAGS ?= -Os
|
||||
CFLAGS += $(OPT_FLAGS)
|
||||
LDFLAGS += $(OPT_FLAGS)
|
||||
|
||||
|
@ -91,47 +91,54 @@
|
||||
#define SWDIO_MODE_DRIVE() \
|
||||
gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \
|
||||
GPIO_PUPD_NONE, SWDIO_PIN);
|
||||
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_TX_PIN); \
|
||||
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_PP, \
|
||||
GPIO_OSPEED_100MHZ, USBUSART_TX_PIN); \
|
||||
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_TX_PIN); \
|
||||
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, \
|
||||
USBUSART_RX_PIN); \
|
||||
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_OD, \
|
||||
GPIO_OSPEED_100MHZ, USBUSART_RX_PIN); \
|
||||
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
|
||||
#define USB_DRIVER stm32f107_usb_driver
|
||||
#define USB_IRQ NVIC_OTG_FS_IRQ
|
||||
#define USB_ISR otg_fs_isr
|
||||
#define USB_ISR(x) otg_fs_isr(x)
|
||||
/* Interrupt priorities. Low numbers are high priority.
|
||||
* For now USART1 preempts USB which may spin while buffer is drained.
|
||||
* TIM3 is used for traceswo capture and must be highest priority.
|
||||
*/
|
||||
#define IRQ_PRI_USB (2 << 4)
|
||||
#define IRQ_PRI_USBUSART (1 << 4)
|
||||
#define IRQ_PRI_USBUSART_TIM (3 << 4)
|
||||
#define IRQ_PRI_USB (1 << 4)
|
||||
#define IRQ_PRI_USBUSART (2 << 4)
|
||||
#define IRQ_PRI_USBUSART_DMA (2 << 4)
|
||||
#define IRQ_PRI_TRACE (0 << 4)
|
||||
|
||||
#define USBUSART USART3
|
||||
#define USBUSART_CR1 USART3_CR1
|
||||
#define USBUSART_DR USART3_DR
|
||||
#define USBUSART_IRQ NVIC_USART3_IRQ
|
||||
#define USBUSART_CLK RCC_USART3
|
||||
#define USBUSART_TX_PORT GPIOD
|
||||
#define USBUSART_TX_PIN GPIO8
|
||||
#define USBUSART_RX_PORT GPIOD
|
||||
#define USBUSART_RX_PIN GPIO9
|
||||
#define USBUSART_ISR usart3_isr
|
||||
#define USBUSART_TIM TIM4
|
||||
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
|
||||
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
|
||||
#define USBUSART_TIM_ISR tim4_isr
|
||||
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_TX_PIN); \
|
||||
gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_RX_PIN); \
|
||||
gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \
|
||||
gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
#define USBUSART_PORT GPIOD
|
||||
#define USBUSART_TX_PIN GPIO8
|
||||
#define USBUSART_RX_PIN GPIO9
|
||||
#define USBUSART_ISR(x) usart3_isr(x)
|
||||
#define USBUSART_DMA_BUS DMA1
|
||||
#define USBUSART_DMA_CLK RCC_DMA1
|
||||
#define USBUSART_DMA_TX_CHAN DMA_STREAM3
|
||||
#define USBUSART_DMA_TX_IRQ NVIC_DMA1_STREAM3_IRQ
|
||||
#define USBUSART_DMA_TX_ISR(x) dma1_stream3_isr(x)
|
||||
#define USBUSART_DMA_RX_CHAN DMA_STREAM1
|
||||
#define USBUSART_DMA_RX_IRQ NVIC_DMA1_STREAM1_IRQ
|
||||
#define USBUSART_DMA_RX_ISR(x) dma1_stream1_isr(x)
|
||||
/* For STM32F4 DMA trigger source must be specified */
|
||||
#define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4
|
||||
|
||||
#define TRACE_TIM TIM3
|
||||
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
|
||||
#define TRACE_IRQ NVIC_TIM3_IRQ
|
||||
#define TRACE_ISR tim3_isr
|
||||
#define TRACE_ISR(x) tim3_isr(x)
|
||||
|
||||
#define gpio_set_val(port, pin, val) do { \
|
||||
if(val) \
|
||||
|
@ -178,6 +178,7 @@ static int scan_linux_id(char *name, char *type, char *version, char *serial)
|
||||
return -1;
|
||||
}
|
||||
strncpy(type, name, p - name);
|
||||
type[p - name] = 0;
|
||||
name = p;
|
||||
while (*name != 'v')
|
||||
name++;
|
||||
@ -191,6 +192,7 @@ static int scan_linux_id(char *name, char *type, char *version, char *serial)
|
||||
return -1;
|
||||
}
|
||||
strncpy(version, name, p - name);
|
||||
version[p - name] = 0;
|
||||
name = p;
|
||||
while (*name == '_')
|
||||
name++;
|
||||
@ -204,6 +206,7 @@ static int scan_linux_id(char *name, char *type, char *version, char *serial)
|
||||
return -1;
|
||||
}
|
||||
strncpy(serial, name, p - name);
|
||||
serial[p - name] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -245,8 +248,8 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
if (found_bmps < 1) {
|
||||
DEBUG_WARN("No BMP probe found\n");
|
||||
return -1;
|
||||
} else if (found_bmps > 1) {
|
||||
DEBUG_INFO("Available Probes:\n");
|
||||
} else if ((found_bmps > 1) || cl_opts->opt_list_only) {
|
||||
DEBUG_WARN("Available Probes:\n");
|
||||
}
|
||||
dir = opendir(DEVICE_BY_ID);
|
||||
i = 0;
|
||||
@ -258,7 +261,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
if (scan_linux_id(dp->d_name, type, version, serial)) {
|
||||
DEBUG_WARN("Unexpected device name found \"%s\"\n",
|
||||
dp->d_name);
|
||||
} else if (found_bmps == 1) {
|
||||
} else if ((found_bmps == 1) && (!cl_opts->opt_list_only)) {
|
||||
strncpy(info->serial, serial, sizeof(info->serial));
|
||||
found_bmps = 1;
|
||||
strncpy(info->serial, serial, sizeof(info->serial));
|
||||
@ -266,13 +269,13 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
|
||||
strncpy(info->product, type, sizeof(info->product));
|
||||
strncpy(info->version, version, sizeof(info->version));
|
||||
break;
|
||||
} else if (found_bmps > 1) {
|
||||
} else if (found_bmps > 0) {
|
||||
DEBUG_WARN("%2d: %s, Black Sphere Technologies, Black Magic "
|
||||
"Probe (%s), %s\n", i, serial, type, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
return (found_bmps == 1) ? 0 : 1;
|
||||
return (found_bmps == 1 && !cl_opts->opt_list_only) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "ftdi_bmp.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include <ftdi.h>
|
||||
|
||||
struct ftdi_context *ftdic;
|
||||
|
||||
|
@ -117,7 +117,7 @@ void libftdi_max_frequency_set(uint32_t freq) {};
|
||||
uint32_t libftdi_max_frequency_get(void) {return 0;};
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include <ftdi.h>
|
||||
extern cable_desc_t cable_desc[];
|
||||
extern cable_desc_t *active_cable;
|
||||
extern struct ftdi_context *ftdic;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include <ftdi.h>
|
||||
#include "platform.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "general.h"
|
||||
#include <libftdi1/ftdi.h>
|
||||
#include <ftdi.h>
|
||||
#include "platform.h"
|
||||
#include "ftdi_bmp.h"
|
||||
|
||||
|
@ -90,47 +90,54 @@
|
||||
#define SWDIO_MODE_DRIVE() \
|
||||
gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \
|
||||
GPIO_PUPD_NONE, SWDIO_PIN);
|
||||
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_TX_PIN); \
|
||||
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_PP, \
|
||||
GPIO_OSPEED_100MHZ, USBUSART_TX_PIN); \
|
||||
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_TX_PIN); \
|
||||
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, \
|
||||
USBUSART_RX_PIN); \
|
||||
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_OD, \
|
||||
GPIO_OSPEED_100MHZ, USBUSART_RX_PIN); \
|
||||
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
|
||||
#define USB_DRIVER stm32f107_usb_driver
|
||||
#define USB_IRQ NVIC_OTG_FS_IRQ
|
||||
#define USB_ISR otg_fs_isr
|
||||
#define USB_ISR(x) otg_fs_isr(x)
|
||||
/* Interrupt priorities. Low numbers are high priority.
|
||||
* For now USART1 preempts USB which may spin while buffer is drained.
|
||||
* TIM3 is used for traceswo capture and must be highest priority.
|
||||
*/
|
||||
#define IRQ_PRI_USB (2 << 4)
|
||||
#define IRQ_PRI_USBUSART (1 << 4)
|
||||
#define IRQ_PRI_USBUSART_TIM (3 << 4)
|
||||
#define IRQ_PRI_USB (1 << 4)
|
||||
#define IRQ_PRI_USBUSART (2 << 4)
|
||||
#define IRQ_PRI_USBUSART_DMA (2 << 4)
|
||||
#define IRQ_PRI_TRACE (0 << 4)
|
||||
|
||||
#define USBUSART USART1
|
||||
#define USBUSART_CR1 USART1_CR1
|
||||
#define USBUSART_DR USART1_DR
|
||||
#define USBUSART_IRQ NVIC_USART1_IRQ
|
||||
#define USBUSART_CLK RCC_USART1
|
||||
#define USBUSART_TX_PORT GPIOA
|
||||
#define USBUSART_TX_PIN GPIO9
|
||||
#define USBUSART_RX_PORT GPIOA
|
||||
#define USBUSART_RX_PIN GPIO10
|
||||
#define USBUSART_ISR usart1_isr
|
||||
#define USBUSART_TIM TIM4
|
||||
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
|
||||
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
|
||||
#define USBUSART_TIM_ISR tim4_isr
|
||||
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_TX_PIN); \
|
||||
gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
|
||||
USBUSART_RX_PIN); \
|
||||
gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \
|
||||
gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
#define USBUSART_PORT GPIOA
|
||||
#define USBUSART_TX_PIN GPIO9
|
||||
#define USBUSART_RX_PIN GPIO10
|
||||
#define USBUSART_ISR(x) usart1_isr(x)
|
||||
#define USBUSART_DMA_BUS DMA2
|
||||
#define USBUSART_DMA_CLK RCC_DMA2
|
||||
#define USBUSART_DMA_TX_CHAN DMA_STREAM7
|
||||
#define USBUSART_DMA_TX_IRQ NVIC_DMA2_STREAM7_IRQ
|
||||
#define USBUSART_DMA_TX_ISR(x) dma2_stream7_isr(x)
|
||||
#define USBUSART_DMA_RX_CHAN DMA_STREAM5
|
||||
#define USBUSART_DMA_RX_IRQ NVIC_DMA2_STREAM5_IRQ
|
||||
#define USBUSART_DMA_RX_ISR(x) dma2_stream5_isr(x)
|
||||
/* For STM32F4 DMA trigger source must be specified */
|
||||
#define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4
|
||||
|
||||
#define TRACE_TIM TIM3
|
||||
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
|
||||
#define TRACE_IRQ NVIC_TIM3_IRQ
|
||||
#define TRACE_ISR tim3_isr
|
||||
#define TRACE_ISR(x) tim3_isr(x)
|
||||
|
||||
#define gpio_set_val(port, pin, val) do { \
|
||||
if(val) \
|
||||
@ -182,4 +189,3 @@ static inline int platform_hwversion(void)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -132,39 +132,47 @@ int usbuart_debug_write(const char *buf, size_t len);
|
||||
SWD_CR = cr; \
|
||||
} while(0)
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_50_MHZ, \
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_INPUT, \
|
||||
GPIO_CNF_INPUT_PULL_UPDOWN, USBUSART_RX_PIN); \
|
||||
gpio_set(USBUSART_PORT, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
|
||||
#define USB_DRIVER st_usbfs_v1_usb_driver
|
||||
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
|
||||
#define USB_ISR usb_lp_can_rx0_isr
|
||||
#define USB_ISR(x) usb_lp_can_rx0_isr(x)
|
||||
/* Interrupt priorities. Low numbers are high priority.
|
||||
* For now USART1 preempts USB which may spin while buffer is drained.
|
||||
* TIM3 is used for traceswo capture and must be highest priority.
|
||||
*/
|
||||
#define IRQ_PRI_USB (2 << 4)
|
||||
#define IRQ_PRI_USBUSART (1 << 4)
|
||||
#define IRQ_PRI_USBUSART_TIM (3 << 4)
|
||||
#define IRQ_PRI_USB (1 << 4)
|
||||
#define IRQ_PRI_USBUSART (2 << 4)
|
||||
#define IRQ_PRI_USBUSART_DMA (2 << 4)
|
||||
#define IRQ_PRI_USB_VBUS (14 << 4)
|
||||
#define IRQ_PRI_TRACE (0 << 4)
|
||||
|
||||
#define USBUSART USART1
|
||||
#define USBUSART_CR1 USART1_CR1
|
||||
#define USBUSART_DR USART1_DR
|
||||
#define USBUSART_IRQ NVIC_USART1_IRQ
|
||||
#define USBUSART_CLK RCC_USART1
|
||||
#define USBUSART_PORT GPIOA
|
||||
#define USBUSART_TX_PIN GPIO9
|
||||
#define USBUSART_ISR usart1_isr
|
||||
#define USBUSART_TIM TIM4
|
||||
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
|
||||
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
|
||||
#define USBUSART_TIM_ISR tim4_isr
|
||||
#define USBUSART_RX_PIN GPIO10
|
||||
#define USBUSART_ISR(x) usart1_isr(x)
|
||||
#define USBUSART_DMA_BUS DMA1
|
||||
#define USBUSART_DMA_CLK RCC_DMA1
|
||||
#define USBUSART_DMA_TX_CHAN DMA_CHANNEL4
|
||||
#define USBUSART_DMA_TX_IRQ NVIC_DMA1_CHANNEL4_IRQ
|
||||
#define USBUSART_DMA_TX_ISR(x) dma1_channel4_isr(x)
|
||||
#define USBUSART_DMA_RX_CHAN DMA_CHANNEL5
|
||||
#define USBUSART_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ
|
||||
#define USBUSART_DMA_RX_ISR(x) dma1_channel5_isr(x)
|
||||
|
||||
#define TRACE_TIM TIM3
|
||||
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
|
||||
#define TRACE_IRQ NVIC_TIM3_IRQ
|
||||
#define TRACE_ISR tim3_isr
|
||||
#define TRACE_ISR(x) tim3_isr(x)
|
||||
|
||||
#define SET_RUN_STATE(state) {running_status = (state);}
|
||||
#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);}
|
||||
|
@ -183,7 +183,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
opt->opt_target_dev = 1;
|
||||
opt->opt_flash_size = 16 * 1024 *1024;
|
||||
opt->opt_flash_size = 0xffffffff;
|
||||
opt->opt_flash_start = 0xffffffff;
|
||||
opt->opt_max_swj_frequency = 4000000;
|
||||
while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:Cln:m:M:wVtTa:S:jpP:rR")) != -1) {
|
||||
@ -364,6 +364,10 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
num_targets = platform_jtag_scan(NULL);
|
||||
} else {
|
||||
num_targets = platform_adiv5_swdp_scan(opt->opt_targetid);
|
||||
if (!num_targets) {
|
||||
DEBUG_INFO("Scan SWD failed, trying JTAG!\n");
|
||||
num_targets = platform_jtag_scan(NULL);
|
||||
}
|
||||
}
|
||||
if (!num_targets) {
|
||||
DEBUG_WARN("No target found\n");
|
||||
@ -395,7 +399,8 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
}
|
||||
/* Always scan memory map to find lowest flash */
|
||||
/* List each defined Flash */
|
||||
uint32_t flash_start = 0xffffffff;
|
||||
uint32_t lowest_flash_start = 0xffffffff;
|
||||
uint32_t lowest_flash_size = 0;
|
||||
int n_flash = 0;
|
||||
for (struct target_flash *f = t->flash; f; f = f->next)
|
||||
n_flash++;
|
||||
@ -406,12 +411,16 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
DEBUG_INFO("Flash Start: 0x%08" PRIx32 " length = 0x%" PRIx32
|
||||
" blocksize 0x%" PRIx32 "\n",
|
||||
f->start, (uint32_t)f->length, (uint32_t)f->blocksize);
|
||||
if (f->start < flash_start)
|
||||
flash_start = f->start;
|
||||
if (f->start < lowest_flash_start) {
|
||||
lowest_flash_start = f->start;
|
||||
lowest_flash_size = f->length;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opt->opt_flash_start == 0xffffffff)
|
||||
opt->opt_flash_start = flash_start;
|
||||
opt->opt_flash_start = lowest_flash_start;
|
||||
if (opt->opt_flash_size == 0xffffffff)
|
||||
opt->opt_flash_size = lowest_flash_size;
|
||||
if (opt->opt_mode == BMP_MODE_SWJ_TEST) {
|
||||
switch (t->core[0]) {
|
||||
case 'M':
|
||||
|
@ -3,7 +3,6 @@ ST_BOOTLOADER ?=
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
|
||||
OPT_FLAGS = -Os
|
||||
CFLAGS += -mcpu=cortex-m3 -mthumb \
|
||||
-DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \
|
||||
-I platforms/stm32
|
||||
|
@ -87,33 +87,41 @@ int usbuart_debug_write(const char *buf, size_t len);
|
||||
cr |= (0x1 * SWD_CR_MULT); \
|
||||
SWD_CR = cr; \
|
||||
} while(0)
|
||||
#define UART_PIN_SETUP() \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN);
|
||||
#define UART_PIN_SETUP() do { \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_50_MHZ, \
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_INPUT, \
|
||||
GPIO_CNF_INPUT_PULL_UPDOWN, USBUSART_RX_PIN); \
|
||||
gpio_set(USBUSART_PORT, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
|
||||
#define USB_DRIVER st_usbfs_v1_usb_driver
|
||||
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
|
||||
#define USB_ISR usb_lp_can_rx0_isr
|
||||
/* Interrupt priorities. Low numbers are high priority.
|
||||
* For now USART2 preempts USB which may spin while buffer is drained.
|
||||
*/
|
||||
#define IRQ_PRI_USB (2 << 4)
|
||||
#define IRQ_PRI_USBUSART (1 << 4)
|
||||
#define IRQ_PRI_USBUSART_TIM (3 << 4)
|
||||
#define USB_ISR(x) usb_lp_can_rx0_isr(x)
|
||||
/* Interrupt priorities. Low numbers are high priority. */
|
||||
#define IRQ_PRI_USB (1 << 4)
|
||||
#define IRQ_PRI_USBUSART (2 << 4)
|
||||
#define IRQ_PRI_USBUSART_DMA (2 << 4)
|
||||
#define IRQ_PRI_USB_VBUS (14 << 4)
|
||||
#define IRQ_PRI_SWO_DMA (1 << 4)
|
||||
#define IRQ_PRI_SWO_DMA (0 << 4)
|
||||
|
||||
#define USBUSART USART2
|
||||
#define USBUSART_CR1 USART2_CR1
|
||||
#define USBUSART_DR USART2_DR
|
||||
#define USBUSART_IRQ NVIC_USART2_IRQ
|
||||
#define USBUSART_CLK RCC_USART2
|
||||
#define USBUSART_PORT GPIOA
|
||||
#define USBUSART_TX_PIN GPIO2
|
||||
#define USBUSART_ISR usart2_isr
|
||||
#define USBUSART_TIM TIM4
|
||||
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
|
||||
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
|
||||
#define USBUSART_TIM_ISR tim4_isr
|
||||
#define USBUSART_RX_PIN GPIO3
|
||||
#define USBUSART_ISR(x) usart2_isr(x)
|
||||
#define USBUSART_DMA_BUS DMA1
|
||||
#define USBUSART_DMA_CLK RCC_DMA1
|
||||
#define USBUSART_DMA_TX_CHAN DMA_CHANNEL7
|
||||
#define USBUSART_DMA_TX_IRQ NVIC_DMA1_CHANNEL7_IRQ
|
||||
#define USBUSART_DMA_TX_ISR(x) dma1_channel7_isr(x)
|
||||
#define USBUSART_DMA_RX_CHAN DMA_CHANNEL6
|
||||
#define USBUSART_DMA_RX_IRQ NVIC_DMA1_CHANNEL6_IRQ
|
||||
#define USBUSART_DMA_RX_ISR(x) dma1_channel6_isr(x)
|
||||
|
||||
/* On F103, only USART1 is on AHB2 and can reach 4.5 MBaud at 72 MHz.*/
|
||||
#define SWO_UART USART1
|
||||
@ -172,4 +180,3 @@ extern uint32_t detect_rev(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
#include <libopencm3/stm32/dma.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/scs.h>
|
||||
#include <libopencm3/usb/usbd.h>
|
||||
@ -30,102 +31,143 @@
|
||||
#include "general.h"
|
||||
#include "cdcacm.h"
|
||||
|
||||
#define USBUART_TIMER_FREQ_HZ 1000000U /* 1us per tick */
|
||||
#define USBUART_RUN_FREQ_HZ 5000U /* 200us (or 100 characters at 2Mbps) */
|
||||
#ifdef STM32F4
|
||||
#define dma_channel_reset(dma, channel) dma_stream_reset(dma, channel)
|
||||
#define dma_enable_channel(dma, channel) dma_enable_stream(dma, channel)
|
||||
#define dma_disable_channel(dma, channel) dma_disable_stream(dma, channel)
|
||||
|
||||
#define FIFO_SIZE 128
|
||||
#define DMA_PSIZE_8BIT DMA_SxCR_PSIZE_8BIT
|
||||
#define DMA_MSIZE_8BIT DMA_SxCR_MSIZE_8BIT
|
||||
#define DMA_PL_HIGH DMA_SxCR_PL_HIGH
|
||||
#define DMA_CGIF DMA_ISR_FLAGS
|
||||
#else
|
||||
#define DMA_PSIZE_8BIT DMA_CCR_PSIZE_8BIT
|
||||
#define DMA_MSIZE_8BIT DMA_CCR_MSIZE_8BIT
|
||||
#define DMA_PL_HIGH DMA_CCR_PL_HIGH
|
||||
#define DMA_CGIF DMA_IFCR_CGIF_BIT
|
||||
#endif
|
||||
|
||||
/* RX Fifo buffer */
|
||||
static uint8_t buf_rx[FIFO_SIZE];
|
||||
/* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */
|
||||
static uint8_t buf_rx_in;
|
||||
/* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */
|
||||
#define TX_LED_ACT (1 << 0)
|
||||
#define RX_LED_ACT (1 << 1)
|
||||
|
||||
#define RX_FIFO_SIZE (128)
|
||||
#define TX_BUF_SIZE (128)
|
||||
|
||||
/* TX double buffer */
|
||||
static uint8_t buf_tx[TX_BUF_SIZE * 2];
|
||||
/* Active buffer part idx */
|
||||
static uint8_t buf_tx_act_idx;
|
||||
/* Active buffer part used capacity */
|
||||
static uint8_t buf_tx_act_sz;
|
||||
/* TX transfer complete */
|
||||
static bool tx_trfr_cplt = true;
|
||||
/* RX Fifo buffer with space for copy fn overrun */
|
||||
static uint8_t buf_rx[RX_FIFO_SIZE + sizeof(uint64_t)];
|
||||
/* RX Fifo out pointer, writes assumed to be atomic */
|
||||
static uint8_t buf_rx_out;
|
||||
/* RX usb transfer complete */
|
||||
static bool rx_usb_trfr_cplt = true;
|
||||
|
||||
#ifdef USBUART_DEBUG
|
||||
/* Debug Fifo buffer with space for copy fn overrun */
|
||||
static uint8_t usb_dbg_buf[RX_FIFO_SIZE + sizeof(uint64_t)];
|
||||
/* Debug Fifo in pointer */
|
||||
static uint8_t usb_dbg_in;
|
||||
/* Debug Fifo out pointer */
|
||||
static uint8_t usb_dbg_out;
|
||||
#endif
|
||||
|
||||
static void usbuart_run(void);
|
||||
|
||||
/*
|
||||
* Update led state atomically respecting RX anb TX states.
|
||||
*/
|
||||
static void usbuart_set_led_state(uint8_t ledn, bool state)
|
||||
{
|
||||
CM_ATOMIC_CONTEXT();
|
||||
|
||||
static uint8_t led_state = 0;
|
||||
|
||||
if (state)
|
||||
{
|
||||
led_state |= ledn;
|
||||
gpio_set(LED_PORT_UART, LED_UART);
|
||||
}
|
||||
else
|
||||
{
|
||||
led_state &= ~ledn;
|
||||
if (!led_state)
|
||||
gpio_clear(LED_PORT_UART, LED_UART);
|
||||
}
|
||||
}
|
||||
|
||||
void usbuart_init(void)
|
||||
{
|
||||
/* Enable clocks */
|
||||
rcc_periph_clock_enable(USBUSART_CLK);
|
||||
rcc_periph_clock_enable(USBUSART_DMA_CLK);
|
||||
|
||||
/* Setup UART parameters */
|
||||
UART_PIN_SETUP();
|
||||
|
||||
/* Setup UART parameters. */
|
||||
usart_set_baudrate(USBUSART, 38400);
|
||||
usart_set_databits(USBUSART, 8);
|
||||
usart_set_stopbits(USBUSART, USART_STOPBITS_1);
|
||||
usart_set_mode(USBUSART, USART_MODE_TX_RX);
|
||||
usart_set_parity(USBUSART, USART_PARITY_NONE);
|
||||
usart_set_flow_control(USBUSART, USART_FLOWCONTROL_NONE);
|
||||
USBUSART_CR1 |= USART_CR1_IDLEIE;
|
||||
|
||||
/* Finally enable the USART. */
|
||||
usart_enable(USBUSART);
|
||||
/* Setup USART TX DMA */
|
||||
dma_channel_reset(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, (uint32_t)&USBUSART_DR);
|
||||
dma_enable_memory_increment_mode(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
dma_set_peripheral_size(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_PSIZE_8BIT);
|
||||
dma_set_memory_size(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_MSIZE_8BIT);
|
||||
dma_set_priority(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_PL_HIGH);
|
||||
dma_enable_transfer_complete_interrupt(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
#ifdef STM32F4
|
||||
dma_set_transfer_mode(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
|
||||
dma_channel_select(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, USBUSART_DMA_TRG);
|
||||
dma_set_dma_flow_control(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
dma_enable_direct_mode(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
#else
|
||||
dma_set_read_from_memory(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
#endif
|
||||
|
||||
/* Setup USART RX DMA */
|
||||
dma_channel_reset(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, (uint32_t)&USBUSART_DR);
|
||||
dma_set_memory_address(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, (uint32_t)buf_rx);
|
||||
dma_set_number_of_data(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, RX_FIFO_SIZE);
|
||||
dma_enable_memory_increment_mode(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
dma_enable_circular_mode(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
dma_set_peripheral_size(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_PSIZE_8BIT);
|
||||
dma_set_memory_size(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_MSIZE_8BIT);
|
||||
dma_set_priority(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_PL_HIGH);
|
||||
dma_enable_half_transfer_interrupt(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
dma_enable_transfer_complete_interrupt(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
#ifdef STM32F4
|
||||
dma_set_transfer_mode(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
|
||||
dma_channel_select(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, USBUSART_DMA_TRG);
|
||||
dma_set_dma_flow_control(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
dma_enable_direct_mode(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
#else
|
||||
dma_set_read_from_peripheral(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
#endif
|
||||
dma_enable_channel(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
|
||||
|
||||
/* Enable interrupts */
|
||||
USBUSART_CR1 |= USART_CR1_RXNEIE;
|
||||
nvic_set_priority(USBUSART_IRQ, IRQ_PRI_USBUSART);
|
||||
nvic_set_priority(USBUSART_DMA_TX_IRQ, IRQ_PRI_USBUSART_DMA);
|
||||
nvic_set_priority(USBUSART_DMA_RX_IRQ, IRQ_PRI_USBUSART_DMA);
|
||||
nvic_enable_irq(USBUSART_IRQ);
|
||||
nvic_enable_irq(USBUSART_DMA_TX_IRQ);
|
||||
nvic_enable_irq(USBUSART_DMA_RX_IRQ);
|
||||
|
||||
/* Setup timer for running deferred FIFO processing */
|
||||
USBUSART_TIM_CLK_EN();
|
||||
timer_set_mode(USBUSART_TIM, TIM_CR1_CKD_CK_INT,
|
||||
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
||||
timer_set_prescaler(USBUSART_TIM,
|
||||
rcc_apb2_frequency / USBUART_TIMER_FREQ_HZ * 2 - 1);
|
||||
timer_set_period(USBUSART_TIM,
|
||||
USBUART_TIMER_FREQ_HZ / USBUART_RUN_FREQ_HZ - 1);
|
||||
|
||||
/* Setup update interrupt in NVIC */
|
||||
nvic_set_priority(USBUSART_TIM_IRQ, IRQ_PRI_USBUSART_TIM);
|
||||
nvic_enable_irq(USBUSART_TIM_IRQ);
|
||||
|
||||
/* turn the timer on */
|
||||
timer_enable_counter(USBUSART_TIM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs deferred processing for usb uart rx, draining RX FIFO by sending
|
||||
* characters to host PC via CDCACM. Allowed to read from FIFO in pointer,
|
||||
* but not write to it. Allowed to write to FIFO out pointer.
|
||||
*/
|
||||
static void usbuart_run(void)
|
||||
{
|
||||
/* forcibly empty fifo if no USB endpoint */
|
||||
if (cdcacm_get_config() != 1)
|
||||
{
|
||||
buf_rx_out = buf_rx_in;
|
||||
}
|
||||
|
||||
/* if fifo empty, nothing further to do */
|
||||
if (buf_rx_in == buf_rx_out) {
|
||||
/* turn off LED, disable IRQ */
|
||||
timer_disable_irq(USBUSART_TIM, TIM_DIER_UIE);
|
||||
gpio_clear(LED_PORT_UART, LED_UART);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t packet_buf[CDCACM_PACKET_SIZE];
|
||||
uint8_t packet_size = 0;
|
||||
uint8_t buf_out = buf_rx_out;
|
||||
|
||||
/* copy from uart FIFO into local usb packet buffer */
|
||||
while (buf_rx_in != buf_out && packet_size < CDCACM_PACKET_SIZE)
|
||||
{
|
||||
packet_buf[packet_size++] = buf_rx[buf_out++];
|
||||
|
||||
/* wrap out pointer */
|
||||
if (buf_out >= FIFO_SIZE)
|
||||
{
|
||||
buf_out = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* advance fifo out pointer by amount written */
|
||||
buf_rx_out += usbd_ep_write_packet(usbdev,
|
||||
CDCACM_UART_ENDPOINT, packet_buf, packet_size);
|
||||
buf_rx_out %= FIFO_SIZE;
|
||||
}
|
||||
/* Finally enable the USART */
|
||||
usart_enable(USBUSART);
|
||||
usart_enable_tx_dma(USBUSART);
|
||||
usart_enable_rx_dma(USBUSART);
|
||||
}
|
||||
|
||||
void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
|
||||
@ -133,9 +175,9 @@ void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
|
||||
usart_set_baudrate(USBUSART, coding->dwDTERate);
|
||||
|
||||
if (coding->bParityType)
|
||||
usart_set_databits(USBUSART, coding->bDataBits + 1);
|
||||
usart_set_databits(USBUSART, (coding->bDataBits + 1 <= 8 ? 8 : 9));
|
||||
else
|
||||
usart_set_databits(USBUSART, coding->bDataBits);
|
||||
usart_set_databits(USBUSART, (coding->bDataBits <= 8 ? 8 : 9));
|
||||
|
||||
switch(coding->bCharFormat) {
|
||||
case 0:
|
||||
@ -145,6 +187,7 @@ void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
|
||||
usart_set_stopbits(USBUSART, USART_STOPBITS_1_5);
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
usart_set_stopbits(USBUSART, USART_STOPBITS_2);
|
||||
break;
|
||||
}
|
||||
@ -157,100 +200,240 @@ void usbuart_set_line_coding(struct usb_cdc_line_coding *coding)
|
||||
usart_set_parity(USBUSART, USART_PARITY_ODD);
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
usart_set_parity(USBUSART, USART_PARITY_EVEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from fifo into continuous buffer. Return copied length.
|
||||
*/
|
||||
static uint32_t copy_from_fifo(uint8_t *dst, const uint8_t *src, uint32_t start, uint32_t end, uint32_t len, uint32_t fifo_sz)
|
||||
{
|
||||
uint32_t out_len = 0;
|
||||
for (uint32_t buf_out = start; buf_out != end && out_len < len; buf_out %= fifo_sz)
|
||||
dst[out_len++] = src[buf_out++];
|
||||
|
||||
return out_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes USBUSART TX buffer in which data is accumulated from USB.
|
||||
* Filled buffer is submitted to DMA for transfer.
|
||||
*/
|
||||
static void usbuart_change_dma_tx_buf(void)
|
||||
{
|
||||
/* Select buffer for transmission */
|
||||
uint8_t *const tx_buf_ptr = &buf_tx[buf_tx_act_idx * TX_BUF_SIZE];
|
||||
|
||||
/* Configure DMA */
|
||||
dma_set_memory_address(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, (uint32_t)tx_buf_ptr);
|
||||
dma_set_number_of_data(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, buf_tx_act_sz);
|
||||
dma_enable_channel(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
|
||||
/* Change active buffer */
|
||||
buf_tx_act_sz = 0;
|
||||
buf_tx_act_idx ^= 1;
|
||||
}
|
||||
|
||||
void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep)
|
||||
{
|
||||
(void)ep;
|
||||
|
||||
char buf[CDCACM_PACKET_SIZE];
|
||||
int len = usbd_ep_read_packet(dev, CDCACM_UART_ENDPOINT,
|
||||
buf, CDCACM_PACKET_SIZE);
|
||||
usbd_ep_nak_set(dev, CDCACM_UART_ENDPOINT, 1);
|
||||
|
||||
/* Read new packet directly into TX buffer */
|
||||
uint8_t *const tx_buf_ptr = &buf_tx[buf_tx_act_idx * TX_BUF_SIZE];
|
||||
const uint16_t len = usbd_ep_read_packet(dev, CDCACM_UART_ENDPOINT,
|
||||
tx_buf_ptr + buf_tx_act_sz, CDCACM_PACKET_SIZE);
|
||||
|
||||
#if defined(BLACKMAGIC)
|
||||
/* Don't bother if uart is disabled.
|
||||
* This will be the case on mini while we're being debugged.
|
||||
*/
|
||||
if(!(RCC_APB2ENR & RCC_APB2ENR_USART1EN))
|
||||
{
|
||||
usbd_ep_nak_set(dev, CDCACM_UART_ENDPOINT, 0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
gpio_set(LED_PORT_UART, LED_UART);
|
||||
for(int i = 0; i < len; i++)
|
||||
usart_send_blocking(USBUSART, buf[i]);
|
||||
gpio_clear(LED_PORT_UART, LED_UART);
|
||||
if (len)
|
||||
{
|
||||
buf_tx_act_sz += len;
|
||||
|
||||
/* If DMA is idle, schedule new transfer */
|
||||
if (tx_trfr_cplt)
|
||||
{
|
||||
tx_trfr_cplt = false;
|
||||
usbuart_change_dma_tx_buf();
|
||||
|
||||
/* Enable LED */
|
||||
usbuart_set_led_state(TX_LED_ACT, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable USBUART TX packet reception if buffer has enough space */
|
||||
if (TX_BUF_SIZE - buf_tx_act_sz >= CDCACM_PACKET_SIZE)
|
||||
usbd_ep_nak_set(dev, CDCACM_UART_ENDPOINT, 0);
|
||||
}
|
||||
|
||||
#ifdef USBUART_DEBUG
|
||||
int usbuart_debug_write(const char *buf, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (buf[i] == '\n') {
|
||||
buf_rx[buf_rx_in++] = '\r';
|
||||
buf_rx_in %= FIFO_SIZE;
|
||||
if (nvic_get_active_irq(USB_IRQ) || nvic_get_active_irq(USBUSART_IRQ) || nvic_get_active_irq(USBUSART_DMA_RX_IRQ))
|
||||
return 0;
|
||||
|
||||
CM_ATOMIC_CONTEXT();
|
||||
|
||||
for (size_t i = 0; i < len && (usb_dbg_in + 1) % RX_FIFO_SIZE != usb_dbg_out; i++)
|
||||
{
|
||||
if (buf[i] == '\n')
|
||||
{
|
||||
usb_dbg_buf[usb_dbg_in++] = '\r';
|
||||
usb_dbg_in %= RX_FIFO_SIZE;
|
||||
|
||||
if ((usb_dbg_in + 1) % RX_FIFO_SIZE == usb_dbg_out)
|
||||
break;
|
||||
}
|
||||
buf_rx[buf_rx_in++] = buf[i];
|
||||
buf_rx_in %= FIFO_SIZE;
|
||||
usb_dbg_buf[usb_dbg_in++] = buf[i];
|
||||
usb_dbg_in %= RX_FIFO_SIZE;
|
||||
}
|
||||
/* enable deferred processing if we put data in the FIFO */
|
||||
timer_enable_irq(USBUSART_TIM, TIM_DIER_UIE);
|
||||
|
||||
usbuart_run();
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep)
|
||||
{
|
||||
(void) dev;
|
||||
(void) ep;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a character from the UART RX and stuff it in a software FIFO.
|
||||
* Allowed to read from FIFO out pointer, but not write to it.
|
||||
* Allowed to write to FIFO in pointer.
|
||||
* Runs deferred processing for USBUSART RX, draining RX FIFO by sending
|
||||
* characters to host PC via CDCACM. Allowed to write to FIFO OUT pointer.
|
||||
*/
|
||||
void USBUSART_ISR(void)
|
||||
static void usbuart_send_rx_packet(void)
|
||||
{
|
||||
uint32_t err = USART_SR(USBUSART);
|
||||
char c = usart_recv(USBUSART);
|
||||
#if !defined(USART_SR_NE) && defined(USART_ISR_NF)
|
||||
# define USART_SR_NE USART_ISR_NF
|
||||
rx_usb_trfr_cplt = false;
|
||||
/* Calculate writing position in the FIFO */
|
||||
const uint32_t buf_rx_in = (RX_FIFO_SIZE - dma_get_number_of_data(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN)) % RX_FIFO_SIZE;
|
||||
|
||||
/* Forcibly empty fifo if no USB endpoint.
|
||||
* If fifo empty, nothing further to do. */
|
||||
if (cdcacm_get_config() != 1 || (buf_rx_in == buf_rx_out
|
||||
#ifdef USBUART_DEBUG
|
||||
&& usb_dbg_in == usb_dbg_out
|
||||
#endif
|
||||
if (err & (USART_FLAG_ORE | USART_FLAG_FE | USART_SR_NE))
|
||||
return;
|
||||
|
||||
/* Turn on LED */
|
||||
gpio_set(LED_PORT_UART, LED_UART);
|
||||
|
||||
/* If the next increment of rx_in would put it at the same point
|
||||
* as rx_out, the FIFO is considered full.
|
||||
*/
|
||||
if (((buf_rx_in + 1) % FIFO_SIZE) != buf_rx_out)
|
||||
))
|
||||
{
|
||||
/* insert into FIFO */
|
||||
buf_rx[buf_rx_in++] = c;
|
||||
#ifdef USBUART_DEBUG
|
||||
usb_dbg_out = usb_dbg_in;
|
||||
#endif
|
||||
buf_rx_out = buf_rx_in;
|
||||
/* Turn off LED */
|
||||
usbuart_set_led_state(RX_LED_ACT, false);
|
||||
rx_usb_trfr_cplt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* To avoid the need of sending ZLP don't transmit full packet.
|
||||
* Also reserve space for copy function overrun.
|
||||
*/
|
||||
uint8_t packet_buf[CDCACM_PACKET_SIZE - 1 + sizeof(uint64_t)];
|
||||
uint32_t packet_size;
|
||||
|
||||
/* wrap out pointer */
|
||||
if (buf_rx_in >= FIFO_SIZE)
|
||||
#ifdef USBUART_DEBUG
|
||||
/* Copy data from DEBUG FIFO into local usb packet buffer */
|
||||
packet_size = copy_from_fifo(packet_buf, usb_dbg_buf, usb_dbg_out, usb_dbg_in, CDCACM_PACKET_SIZE - 1, RX_FIFO_SIZE);
|
||||
/* Send if buffer not empty */
|
||||
if (packet_size)
|
||||
{
|
||||
buf_rx_in = 0;
|
||||
const uint16_t written = usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, packet_buf, packet_size);
|
||||
usb_dbg_out = (usb_dbg_out + written) % RX_FIFO_SIZE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* enable deferred processing if we put data in the FIFO */
|
||||
timer_enable_irq(USBUSART_TIM, TIM_DIER_UIE);
|
||||
/* Copy data from uart RX FIFO into local usb packet buffer */
|
||||
packet_size = copy_from_fifo(packet_buf, buf_rx, buf_rx_out, buf_rx_in, CDCACM_PACKET_SIZE - 1, RX_FIFO_SIZE);
|
||||
|
||||
/* Advance fifo out pointer by amount written */
|
||||
const uint16_t written = usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, packet_buf, packet_size);
|
||||
buf_rx_out = (buf_rx_out + written) % RX_FIFO_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void USBUSART_TIM_ISR(void)
|
||||
void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep)
|
||||
{
|
||||
/* need to clear timer update event */
|
||||
timer_clear_flag(USBUSART_TIM, TIM_SR_UIF);
|
||||
(void) ep;
|
||||
(void) dev;
|
||||
|
||||
/* process FIFO */
|
||||
usbuart_send_rx_packet();
|
||||
}
|
||||
|
||||
static void usbuart_run(void)
|
||||
{
|
||||
nvic_disable_irq(USB_IRQ);
|
||||
|
||||
/* Enable LED */
|
||||
usbuart_set_led_state(RX_LED_ACT, true);
|
||||
|
||||
/* Try to send a packet if usb is idle */
|
||||
if (rx_usb_trfr_cplt)
|
||||
usbuart_send_rx_packet();
|
||||
|
||||
nvic_enable_irq(USB_IRQ);
|
||||
}
|
||||
|
||||
void USBUSART_ISR(void)
|
||||
{
|
||||
nvic_disable_irq(USBUSART_DMA_RX_IRQ);
|
||||
|
||||
/* Get IDLE flag and reset interrupt flags */
|
||||
const bool isIdle = usart_get_flag(USBUSART, USART_FLAG_IDLE);
|
||||
usart_recv(USBUSART);
|
||||
|
||||
/* If line is now idle, then transmit a packet */
|
||||
if (isIdle)
|
||||
usbuart_run();
|
||||
|
||||
nvic_enable_irq(USBUSART_DMA_RX_IRQ);
|
||||
}
|
||||
|
||||
void USBUSART_DMA_TX_ISR(void)
|
||||
{
|
||||
nvic_disable_irq(USB_IRQ);
|
||||
|
||||
/* Stop DMA */
|
||||
dma_disable_channel(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
|
||||
dma_clear_interrupt_flags(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_CGIF);
|
||||
|
||||
/* If new buffer is ready, continue transmission.
|
||||
* Otherwise report transfer completion.
|
||||
*/
|
||||
if (buf_tx_act_sz)
|
||||
{
|
||||
usbuart_change_dma_tx_buf();
|
||||
usbd_ep_nak_set(usbdev, CDCACM_UART_ENDPOINT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
usbuart_set_led_state(TX_LED_ACT, false);
|
||||
tx_trfr_cplt = true;
|
||||
}
|
||||
|
||||
nvic_enable_irq(USB_IRQ);
|
||||
}
|
||||
|
||||
void USBUSART_DMA_RX_ISR(void)
|
||||
{
|
||||
nvic_disable_irq(USBUSART_IRQ);
|
||||
|
||||
/* Clear flags */
|
||||
dma_clear_interrupt_flags(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_CGIF);
|
||||
/* Transmit a packet */
|
||||
usbuart_run();
|
||||
|
||||
nvic_enable_irq(USBUSART_IRQ);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
|
@ -2,7 +2,6 @@ CROSS_COMPILE ?= arm-none-eabi-
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
|
||||
OPT_FLAGS = -Os
|
||||
CFLAGS += -mcpu=cortex-m3 -mthumb \
|
||||
-DSTM32F1 -DDISCOVERY_SWLINK -I../libopencm3/include \
|
||||
-I platforms/stm32
|
||||
|
@ -83,39 +83,47 @@ int usbuart_debug_write(const char *buf, size_t len);
|
||||
} while(0)
|
||||
#define UART_PIN_SETUP() do { \
|
||||
AFIO_MAPR |= AFIO_MAPR_USART1_REMAP; \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_50_MHZ, \
|
||||
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \
|
||||
} while (0)
|
||||
gpio_set_mode(USBUSART_PORT, GPIO_MODE_INPUT, \
|
||||
GPIO_CNF_INPUT_PULL_UPDOWN, USBUSART_RX_PIN); \
|
||||
gpio_set(USBUSART_PORT, USBUSART_RX_PIN); \
|
||||
} while(0)
|
||||
|
||||
#define USB_DRIVER st_usbfs_v1_usb_driver
|
||||
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
|
||||
#define USB_ISR usb_lp_can_rx0_isr
|
||||
#define USB_ISR(x) usb_lp_can_rx0_isr(x)
|
||||
/* Interrupt priorities. Low numbers are high priority.
|
||||
* For now USART1 preempts USB which may spin while buffer is drained.
|
||||
* TIM2 is used for traceswo capture and must be highest priority.
|
||||
*/
|
||||
#define IRQ_PRI_USB (2 << 4)
|
||||
#define IRQ_PRI_USBUSART (1 << 4)
|
||||
#define IRQ_PRI_USBUSART_TIM (3 << 4)
|
||||
#define IRQ_PRI_USB (1 << 4)
|
||||
#define IRQ_PRI_USBUSART (2 << 4)
|
||||
#define IRQ_PRI_USBUSART_DMA (2 << 4)
|
||||
#define IRQ_PRI_USB_VBUS (14 << 4)
|
||||
#define IRQ_PRI_SWO_DMA (0 << 4)
|
||||
|
||||
#define USBUSART USART1
|
||||
#define USBUSART_CR1 USART1_CR1
|
||||
#define USBUSART_DR USART1_DR
|
||||
#define USBUSART_IRQ NVIC_USART1_IRQ
|
||||
#define USBUSART_CLK RCC_USART1
|
||||
#define USBUSART_PORT GPIOB
|
||||
#define USBUSART_TX_PIN GPIO6
|
||||
#define USBUSART_ISR usart1_isr
|
||||
#define USBUSART_TIM TIM4
|
||||
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
|
||||
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
|
||||
#define USBUSART_TIM_ISR tim4_isr
|
||||
#define USBUSART_RX_PIN GPIO7
|
||||
#define USBUSART_ISR(x) usart1_isr(x)
|
||||
#define USBUSART_DMA_BUS DMA1
|
||||
#define USBUSART_DMA_CLK RCC_DMA1
|
||||
#define USBUSART_DMA_TX_CHAN DMA_CHANNEL4
|
||||
#define USBUSART_DMA_TX_IRQ NVIC_DMA1_CHANNEL4_IRQ
|
||||
#define USBUSART_DMA_TX_ISR(x) dma1_channel4_isr(x)
|
||||
#define USBUSART_DMA_RX_CHAN DMA_CHANNEL5
|
||||
#define USBUSART_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ
|
||||
#define USBUSART_DMA_RX_ISR(x) dma1_channel5_isr(x)
|
||||
|
||||
#define TRACE_TIM TIM2
|
||||
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2)
|
||||
#define TRACE_IRQ NVIC_TIM2_IRQ
|
||||
#define TRACE_ISR tim2_isr
|
||||
#define TRACE_ISR(x) tim2_isr(x)
|
||||
#define TRACE_IC_IN TIM_IC_IN_TI2
|
||||
#define TRACE_TRIG_IN TIM_SMCR_TS_IT1FP2
|
||||
|
||||
@ -177,4 +185,3 @@ extern uint8_t detect_rev(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -413,7 +413,17 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
||||
addr &= 0xfffff000; /* Mask out base address */
|
||||
if (addr == 0) /* No rom table on this AP */
|
||||
return;
|
||||
uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
volatile uint32_t cidr;
|
||||
volatile struct exception e;
|
||||
TRY_CATCH (e, EXCEPTION_TIMEOUT) {
|
||||
cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
}
|
||||
if (e.type) {
|
||||
DEBUG_WARN("CIDR read timeout on AP%d, aborting.\n", num_entry);
|
||||
adiv5_dp_abort(ap->dp, ADIV5_DP_ABORT_DAPABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE)
|
||||
return;
|
||||
#if defined(ENABLE_DEBUG)
|
||||
@ -603,7 +613,7 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
|
||||
uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG);
|
||||
DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32
|
||||
" CSW=%08"PRIx32, apsel, ap->idr, cfg, ap->base, ap->csw);
|
||||
DEBUG_INFO(" (AHB-AP var%x rev%x)\n",
|
||||
DEBUG_INFO(" (AHB-AP var%" PRIx32 " rev%" PRIx32 "\n",
|
||||
(ap->idr >> 4) & 0xf, ap->idr >> 28);
|
||||
#endif
|
||||
adiv5_ap_ref(ap);
|
||||
@ -620,7 +630,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
|
||||
free(dp);
|
||||
return;
|
||||
}
|
||||
DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode,
|
||||
DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%" PRId32 " %srev%" PRId32 ")\n",
|
||||
dp->idcode,
|
||||
(dp->idcode >> 12) & 0xf,
|
||||
(dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28);
|
||||
volatile uint32_t ctrlstat = 0;
|
||||
|
@ -86,7 +86,7 @@ static int cortexm_breakwatch_clear(target *t, struct breakwatch *);
|
||||
static target_addr cortexm_check_watch(target *t);
|
||||
|
||||
#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */
|
||||
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
|
||||
#define CORTEXM_MAX_BREAKPOINTS 8 /* architecture says up to 127, no implementation has > 8 */
|
||||
|
||||
static int cortexm_hostio_request(target *t);
|
||||
|
||||
@ -327,9 +327,11 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
||||
t->core = "M0";
|
||||
break;
|
||||
default:
|
||||
DEBUG_WARN("Unexpected CortexM CPUID partno %04x\n", cpuid_partno);
|
||||
DEBUG_WARN("Unexpected CortexM CPUID partno %04" PRIx32 "\n",
|
||||
cpuid_partno);
|
||||
}
|
||||
DEBUG_INFO("CPUID 0x%08" PRIx32 " (%s var %x rev %x)\n", t->cpuid,
|
||||
DEBUG_INFO("CPUID 0x%08" PRIx32 " (%s var %" PRIx32 " rev %" PRIx32 ")\n",
|
||||
t->cpuid,
|
||||
t->core, (t->cpuid & CPUID_REVISION_MASK) >> 20,
|
||||
t->cpuid & CPUID_PATCH_MASK);
|
||||
|
||||
@ -400,10 +402,6 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
||||
PROBE(stm32l0_probe);
|
||||
PROBE(stm32l4_probe);
|
||||
PROBE(stm32g0_probe);
|
||||
if (ap->ap_partno == 0x472) {
|
||||
t->driver = "STM32L552(no flash)";
|
||||
target_halt_resume(t, 0);
|
||||
}
|
||||
break;
|
||||
case AP_DESIGNER_CYPRESS:
|
||||
DEBUG_WARN("Unhandled Cypress device\n");
|
||||
|
@ -415,7 +415,7 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr,
|
||||
/* Check for error */
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
if(sr & SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32f4 flash erase: sr error: 0x%" PRIu32 "\n", sr);
|
||||
DEBUG_WARN("stm32f4 flash erase: sr error: 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2015, 2017 - 2020 Uwe Bonnes
|
||||
* Copyright (C) 2015, 2017 - 2021 Uwe Bonnes
|
||||
* <bon@elektron.ikp.physik.tu-darmstadt.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
@ -28,7 +28,7 @@
|
||||
* RM0394 STM32L43xxx STM32L44xxx STM32L45xxx STM32L46xxxx advanced
|
||||
* ARM®-based 32-bit MCUs Rev.3
|
||||
* RM0432 STM32L4Rxxx and STM32L4Sxxx advanced Arm®-based 32-bit MCU. Rev 1
|
||||
* RM0440 STM32G4 Series advanced Arm®-based 32-bit MCU. Rev 1
|
||||
* RM0440 STM32G4 Series advanced Arm®-based 32-bit MCU. Rev 6
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ -51,20 +51,16 @@ const struct command_s stm32l4_cmd_list[] = {
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len);
|
||||
static int stm32l4_flash_write(struct target_flash *f,
|
||||
target_addr dest, const void *src, size_t len);
|
||||
|
||||
/* Flash Program ad Erase Controller Register Map */
|
||||
#define FPEC_BASE 0x40022000
|
||||
#define FLASH_ACR (FPEC_BASE+0x00)
|
||||
#define FLASH_KEYR (FPEC_BASE+0x08)
|
||||
#define FLASH_OPTKEYR (FPEC_BASE+0x0c)
|
||||
#define FLASH_SR (FPEC_BASE+0x10)
|
||||
#define FLASH_CR (FPEC_BASE+0x14)
|
||||
#define FLASH_OPTR (FPEC_BASE+0x20)
|
||||
//#define FLASH_OPTCR (FPEC_BASE+0x14)
|
||||
#define L4_FPEC_BASE 0x40022000
|
||||
#define L5_FPEC_BASE 0x40022000
|
||||
#define WL_FPEC_BASE 0x58004000
|
||||
|
||||
#define L5_FLASH_OPTR_TZEN (1 << 31)
|
||||
|
||||
#define FLASH_CR_PG (1 << 0)
|
||||
#define FLASH_CR_PER (1 << 1)
|
||||
@ -95,6 +91,8 @@ static int stm32l4_flash_write(struct target_flash *f,
|
||||
#define FLASH_SR_ERROR_MASK 0xC3FA
|
||||
#define FLASH_SR_BSY (1 << 16)
|
||||
|
||||
#define FLASH_SIZE_MAX_G4_CAT4 (512U * 1024U) // 512 kiB
|
||||
|
||||
#define KEY1 0x45670123
|
||||
#define KEY2 0xCDEF89AB
|
||||
|
||||
@ -107,7 +105,7 @@ static int stm32l4_flash_write(struct target_flash *f,
|
||||
#define OR_DUALBANK (1 << 21)
|
||||
/* Used in STM32L47R*/
|
||||
#define OR_DB1M (1 << 21)
|
||||
/* Used in STM32L47R and STM32G47 */
|
||||
/* Used in STM32L47R, STM32G47 and STM32L55*/
|
||||
#define OR_DBANK (1 << 22)
|
||||
|
||||
#define DBGMCU_CR(dbgmcureg) (dbgmcureg + 0x04)
|
||||
@ -117,8 +115,10 @@ static int stm32l4_flash_write(struct target_flash *f,
|
||||
|
||||
enum {
|
||||
STM32L4_DBGMCU_IDCODE_PHYS = 0xe0042000,
|
||||
STM32L5_DBGMCU_IDCODE_PHYS = 0xe0044000,
|
||||
};
|
||||
#define FLASH_SIZE_REG 0x1FFF75E0
|
||||
#define L4_FLASH_SIZE_REG 0x1FFF75E0
|
||||
#define L5_FLASH_SIZE_REG 0x0bfa05e0
|
||||
|
||||
struct stm32l4_flash {
|
||||
struct target_flash f;
|
||||
@ -138,6 +138,9 @@ enum ID_STM32L4 {
|
||||
ID_STM32L4R = 0x470u, /* RM0432, Rev.5 */
|
||||
ID_STM32G43 = 0x468u, /* RM0440, Rev.1 */
|
||||
ID_STM32G47 = 0x469u, /* RM0440, Rev.1 */
|
||||
ID_STM32G49 = 0x479u, /* RM0440, Rev.6 */
|
||||
ID_STM32L55 = 0x472u, /* RM0438, Rev.4 */
|
||||
ID_STM32WLXX = 0x497u, /* RM0461, Rev.3, RM453, Rev.1 */
|
||||
};
|
||||
|
||||
enum FAM_STM32L4 {
|
||||
@ -145,11 +148,50 @@ enum FAM_STM32L4 {
|
||||
FAM_STM32L4Rx = 2,
|
||||
FAM_STM32WBxx = 4,
|
||||
FAM_STM32G4xx = 5,
|
||||
FAM_STM32L55x = 6,
|
||||
FAM_STM32WLxx = 7,
|
||||
};
|
||||
|
||||
#define DUAL_BANK 0x80u
|
||||
#define RAM_COUNT_MSK 0x07u
|
||||
|
||||
enum stm32l4_flash_regs {
|
||||
FLASH_KEYR,
|
||||
FLASH_OPTKEYR,
|
||||
FLASH_SR,
|
||||
FLASH_CR,
|
||||
FLASH_OPTR,
|
||||
FLASHSIZE,
|
||||
FLASH_REGS_COUNT
|
||||
};
|
||||
|
||||
static const uint32_t stm32l4_flash_regs_map[FLASH_REGS_COUNT] = {
|
||||
L4_FPEC_BASE + 0x08, /* KEYR */
|
||||
L4_FPEC_BASE + 0x0c, /* OPTKEYR */
|
||||
L4_FPEC_BASE + 0x10, /* SR */
|
||||
L4_FPEC_BASE + 0x14, /* CR */
|
||||
L4_FPEC_BASE + 0x20, /* OPTR */
|
||||
L4_FLASH_SIZE_REG, /* FLASHSIZE */
|
||||
};
|
||||
|
||||
static const uint32_t stm32l5_flash_regs_map[FLASH_REGS_COUNT] = {
|
||||
L5_FPEC_BASE + 0x08, /* KEYR */
|
||||
L5_FPEC_BASE + 0x10, /* OPTKEYR */
|
||||
L5_FPEC_BASE + 0x20, /* SR */
|
||||
L5_FPEC_BASE + 0x28, /* CR */
|
||||
L5_FPEC_BASE + 0x40, /* OPTR */
|
||||
L5_FLASH_SIZE_REG, /* FLASHSIZE */
|
||||
};
|
||||
|
||||
static const uint32_t stm32wl_flash_regs_map[FLASH_REGS_COUNT] = {
|
||||
WL_FPEC_BASE + 0x08, /* KEYR */
|
||||
WL_FPEC_BASE + 0x0c, /* OPTKEYR */
|
||||
WL_FPEC_BASE + 0x10, /* SR */
|
||||
WL_FPEC_BASE + 0x14, /* CR */
|
||||
WL_FPEC_BASE + 0x20, /* OPTR */
|
||||
L4_FLASH_SIZE_REG, /* FLASHSIZE */
|
||||
};
|
||||
|
||||
struct stm32l4_info {
|
||||
char designator[10];
|
||||
uint16_t sram1; /* Normal SRAM mapped at 0x20000000*/
|
||||
@ -158,9 +200,10 @@ struct stm32l4_info {
|
||||
enum ID_STM32L4 idcode;
|
||||
enum FAM_STM32L4 family;
|
||||
uint8_t flags; /* Only DUAL_BANK is evaluated for now.*/
|
||||
const uint32_t *flash_regs_map;
|
||||
};
|
||||
|
||||
struct stm32l4_info const L4info[] = {
|
||||
static struct stm32l4_info const L4info[] = {
|
||||
{
|
||||
.idcode = ID_STM32L41,
|
||||
.family = FAM_STM32L4xx,
|
||||
@ -168,6 +211,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram1 = 32,
|
||||
.sram2 = 8,
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L43,
|
||||
@ -176,6 +220,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram1 = 48,
|
||||
.sram2 = 16,
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L45,
|
||||
@ -184,6 +229,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram1 = 128,
|
||||
.sram2 = 32,
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L47,
|
||||
@ -192,6 +238,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram1 = 96,
|
||||
.sram2 = 32,
|
||||
.flags = 2 | DUAL_BANK,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L49,
|
||||
@ -200,6 +247,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram1 = 256,
|
||||
.sram2 = 64,
|
||||
.flags = 2 | DUAL_BANK,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L4R,
|
||||
@ -209,6 +257,7 @@ struct stm32l4_info const L4info[] = {
|
||||
.sram2 = 64,
|
||||
.sram3 = 384,
|
||||
.flags = 3 | DUAL_BANK,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32G43,
|
||||
@ -216,14 +265,43 @@ struct stm32l4_info const L4info[] = {
|
||||
.designator = "STM32G43",
|
||||
.sram1 = 22,
|
||||
.sram2 = 10,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32G47,
|
||||
.family = FAM_STM32G4xx,
|
||||
.designator = "STM32G47",
|
||||
.sram1 = 96, /* SRAM1 and SRAM2 are mapped contigiously */
|
||||
.sram1 = 96, /* SRAM1 and SRAM2 are mapped continuous */
|
||||
.sram2 = 32, /* CCM SRAM is mapped as per SRAM2 on G4 */
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32G49,
|
||||
.family = FAM_STM32G4xx,
|
||||
.designator = "STM32G49",
|
||||
.sram1 = 96, /* SRAM1 and SRAM2 are mapped continuously */
|
||||
.sram2 = 16, /* CCM SRAM is mapped as per SRAM2 on G4 */
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l4_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32L55,
|
||||
.family = FAM_STM32L55x,
|
||||
.designator = "STM32L55",
|
||||
.sram1 = 192, /* SRAM1 and SRAM2 are mapped continuous */
|
||||
.sram2 = 64,
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32l5_flash_regs_map,
|
||||
},
|
||||
{
|
||||
.idcode = ID_STM32WLXX,
|
||||
.family = FAM_STM32WLxx,
|
||||
.designator = "STM32WLxx",
|
||||
.sram1 = 64,
|
||||
.sram2 = 32,
|
||||
.flags = 2,
|
||||
.flash_regs_map = stm32wl_flash_regs_map,
|
||||
},
|
||||
{
|
||||
/* Terminator */
|
||||
@ -240,6 +318,27 @@ static struct stm32l4_info const * stm32l4_get_chip_info(uint32_t idcode) {
|
||||
return p;
|
||||
}
|
||||
|
||||
static uint32_t stm32l4_flash_read16(target *t, enum stm32l4_flash_regs reg)
|
||||
{
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
uint32_t addr = chip->flash_regs_map[reg];
|
||||
return target_mem_read16(t, addr);
|
||||
}
|
||||
|
||||
static uint32_t stm32l4_flash_read32(target *t, enum stm32l4_flash_regs reg)
|
||||
{
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
uint32_t addr = chip->flash_regs_map[reg];
|
||||
return target_mem_read32(t, addr);
|
||||
}
|
||||
|
||||
static void stm32l4_flash_write32(target *t, enum stm32l4_flash_regs reg, uint32_t value)
|
||||
{
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
uint32_t addr = chip->flash_regs_map[reg];
|
||||
target_mem_write32(t, addr, value);
|
||||
}
|
||||
|
||||
static void stm32l4_add_flash(target *t,
|
||||
uint32_t addr, size_t length, size_t blocksize,
|
||||
uint32_t bank1_start)
|
||||
@ -263,6 +362,17 @@ static void stm32l4_add_flash(target *t,
|
||||
sf->bank1_start = bank1_start;
|
||||
target_add_flash(t, f);
|
||||
}
|
||||
#define L5_RCC_APB1ENR1 0x50021058
|
||||
#define L5_RCC_APB1ENR1_PWREN (1 << 28)
|
||||
#define L5_PWR_CR1 0x50007000
|
||||
#define L5_PWR_CR1_VOS (3 << 9)
|
||||
/* For flash programming, L5 needs to be in VOS 0 or 1 while reset set 2 (or even 3?) */
|
||||
static void stm32l5_flash_enable(target *t)
|
||||
{
|
||||
target_mem_write32(t, L5_RCC_APB1ENR1, L5_RCC_APB1ENR1_PWREN);
|
||||
uint32_t pwr_cr1 = target_mem_read32(t, L5_PWR_CR1) & ~L5_PWR_CR1_VOS;
|
||||
target_mem_write32(t, L5_PWR_CR1, pwr_cr1);
|
||||
}
|
||||
|
||||
static bool stm32l4_attach(target *t)
|
||||
{
|
||||
@ -273,9 +383,16 @@ static bool stm32l4_attach(target *t)
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
|
||||
|
||||
uint32_t idcodereg = STM32L4_DBGMCU_IDCODE_PHYS;
|
||||
|
||||
|
||||
uint32_t idcodereg;
|
||||
switch(chip->family) {
|
||||
case FAM_STM32L55x:
|
||||
idcodereg = STM32L5_DBGMCU_IDCODE_PHYS;
|
||||
stm32l5_flash_enable(t);
|
||||
break;
|
||||
default:
|
||||
idcodereg = STM32L4_DBGMCU_IDCODE_PHYS;
|
||||
break;
|
||||
}
|
||||
/* Save DBGMCU_CR to restore it when detaching*/
|
||||
struct stm32l4_priv_s *priv_storage = calloc(1, sizeof(*priv_storage));
|
||||
priv_storage->dbgmcu_cr = target_mem_read32(t, DBGMCU_CR(idcodereg));
|
||||
@ -284,20 +401,22 @@ static bool stm32l4_attach(target *t)
|
||||
/* Enable debugging during all low power modes*/
|
||||
target_mem_write32(t, DBGMCU_CR(idcodereg), DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STANDBY | DBGMCU_CR_DBG_STOP);
|
||||
|
||||
|
||||
/* Free previously loaded memory map */
|
||||
target_mem_map_free(t);
|
||||
|
||||
/* Add RAM to memory map */
|
||||
target_add_ram(t, 0x10000000, chip->sram2 << 10);
|
||||
/* Add Code RAM to memory map */
|
||||
if (chip->family == FAM_STM32L55x)
|
||||
target_add_ram(t, 0x0A000000, (chip->sram1 + chip->sram2) << 10);
|
||||
else
|
||||
target_add_ram(t, 0x10000000, chip->sram2 << 10);
|
||||
/* All L4 beside L47 alias SRAM2 after SRAM1.*/
|
||||
uint32_t ramsize = (t->idcode == ID_STM32L47)?
|
||||
chip->sram1 : (chip->sram1 + chip->sram2 + chip->sram3);
|
||||
target_add_ram(t, 0x20000000, ramsize << 10);
|
||||
|
||||
uint32_t size = stm32l4_flash_read16(t, FLASHSIZE);
|
||||
/* Add the flash to memory map. */
|
||||
uint32_t size = target_mem_read16(t, FLASH_SIZE_REG);
|
||||
uint32_t options = target_mem_read32(t, FLASH_OPTR);
|
||||
uint32_t options = stm32l4_flash_read32(t, FLASH_OPTR);
|
||||
|
||||
if (chip->family == FAM_STM32L4Rx) {
|
||||
/* rm0432 Rev. 2 does not mention 1 MB devices or explain DB1M.*/
|
||||
@ -306,14 +425,26 @@ static bool stm32l4_attach(target *t)
|
||||
stm32l4_add_flash(t, 0x08100000, 0x00100000, 0x1000, 0x08100000);
|
||||
} else
|
||||
stm32l4_add_flash(t, 0x08000000, 0x00200000, 0x2000, -1);
|
||||
} else if (chip->family == FAM_STM32L55x) {
|
||||
/* FIXME: Test behaviour on 256 k devices */
|
||||
if (options & OR_DBANK) {
|
||||
stm32l4_add_flash(t, 0x08000000, 0x00040000, 0x0800, 0x08040000);
|
||||
stm32l4_add_flash(t, 0x08040000, 0x00040000, 0x0800, 0x08040000);
|
||||
} else
|
||||
stm32l4_add_flash(t, 0x08000000, 0x00080000, 0x0800, -1);
|
||||
} else if (chip->family == FAM_STM32G4xx) {
|
||||
// RM0440 describes G43x as Category 2, G47x/G48x as Category 3 devices
|
||||
// RM0440 describes G43x/G44x as Category 2, G47x/G48x as Category 3 and G49x/G4Ax as Category 4 devices
|
||||
// Cat 2 is always 128k with 2k pages, single bank
|
||||
// Cat 3 is dual bank with an option bit to choose single 512k bank with 4k pages or dual bank as 2x256k with 2k pages
|
||||
// Cat 4 is single bank with up to 512k, 2k pages
|
||||
if (chip->idcode == ID_STM32G43) {
|
||||
uint32_t banksize = size << 10;
|
||||
stm32l4_add_flash(t, 0x08000000, banksize, 0x0800, -1);
|
||||
}
|
||||
else if (chip->idcode == ID_STM32G49) {
|
||||
// Announce maximum possible flash size on this chip
|
||||
stm32l4_add_flash(t, 0x08000000, FLASH_SIZE_MAX_G4_CAT4, 0x0800, -1);
|
||||
}
|
||||
else {
|
||||
if (options & OR_DBANK) {
|
||||
uint32_t banksize = size << 9;
|
||||
@ -337,7 +468,7 @@ static bool stm32l4_attach(target *t)
|
||||
stm32l4_add_flash(t, 0x08000000, size << 10, 0x800, -1);
|
||||
|
||||
/* Clear all errors in the status register. */
|
||||
target_mem_write32(t, FLASH_SR, target_mem_read32(t, FLASH_SR));
|
||||
stm32l4_flash_write32(t, FLASH_SR, stm32l4_flash_read32(t, FLASH_SR));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -354,7 +485,18 @@ static void stm32l4_detach(target *t)
|
||||
|
||||
bool stm32l4_probe(target *t)
|
||||
{
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(t->idcode);
|
||||
uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS;
|
||||
ADIv5_AP_t *ap = cortexm_ap(t);
|
||||
if (ap->dp->idcode == 0x0Be12477) {
|
||||
idcode_reg = STM32L5_DBGMCU_IDCODE_PHYS;
|
||||
if ((stm32l4_flash_read32(t, FLASH_OPTR)) & L5_FLASH_OPTR_TZEN) {
|
||||
DEBUG_WARN("STM32L5 Trust Zone enabled\n");
|
||||
}
|
||||
}
|
||||
uint32_t idcode = target_mem_read32(t, idcode_reg) & 0xfff;
|
||||
DEBUG_INFO("Read %" PRIx32 ": %" PRIx32 "\n", idcode_reg, idcode);
|
||||
|
||||
struct stm32l4_info const *chip = stm32l4_get_chip_info(idcode);
|
||||
|
||||
if( !chip->idcode ) /* Not found */
|
||||
return false;
|
||||
@ -368,10 +510,10 @@ bool stm32l4_probe(target *t)
|
||||
|
||||
static void stm32l4_flash_unlock(target *t)
|
||||
{
|
||||
if (target_mem_read32(t, FLASH_CR) & FLASH_CR_LOCK) {
|
||||
if ((stm32l4_flash_read32(t, FLASH_CR)) & FLASH_CR_LOCK) {
|
||||
/* Enable FPEC controller access */
|
||||
target_mem_write32(t, FLASH_KEYR, KEY1);
|
||||
target_mem_write32(t, FLASH_KEYR, KEY2);
|
||||
stm32l4_flash_write32(t, FLASH_KEYR, KEY1);
|
||||
stm32l4_flash_write32(t, FLASH_KEYR, KEY2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,11 +528,11 @@ static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t
|
||||
stm32l4_flash_unlock(t);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
while(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
/* Fixme: OPTVER always set after reset! Wrong option defaults?*/
|
||||
target_mem_write32(t, FLASH_SR, target_mem_read32(t, FLASH_SR));
|
||||
stm32l4_flash_write32(t, FLASH_SR, stm32l4_flash_read32(t, FLASH_SR));
|
||||
page = (addr - 0x08000000) / blocksize;
|
||||
while(len) {
|
||||
uint32_t cr;
|
||||
@ -399,13 +541,13 @@ static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t
|
||||
if (addr >= bank1_start)
|
||||
cr |= FLASH_CR_BKER;
|
||||
/* Flash page erase instruction */
|
||||
target_mem_write32(t, FLASH_CR, cr);
|
||||
stm32l4_flash_write32(t, FLASH_CR, cr);
|
||||
/* write address to FMA */
|
||||
cr |= FLASH_CR_STRT;
|
||||
target_mem_write32(t, FLASH_CR, cr);
|
||||
stm32l4_flash_write32(t, FLASH_CR, cr);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
while(stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
if (len > blocksize)
|
||||
@ -417,7 +559,7 @@ static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if(sr & FLASH_SR_ERROR_MASK)
|
||||
return -1;
|
||||
|
||||
@ -428,12 +570,12 @@ static int stm32l4_flash_write(struct target_flash *f,
|
||||
target_addr dest, const void *src, size_t len)
|
||||
{
|
||||
target *t = f->t;
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_PG);
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_PG);
|
||||
target_mem_write(t, dest, src, len);
|
||||
/* Wait for completion or an error */
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = target_mem_read32(t, FLASH_SR);
|
||||
sr = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if (target_check_error(t)) {
|
||||
DEBUG_WARN("stm32l4 flash write: comm error\n");
|
||||
return -1;
|
||||
@ -441,7 +583,7 @@ static int stm32l4_flash_write(struct target_flash *f,
|
||||
} while (sr & FLASH_SR_BSY);
|
||||
|
||||
if(sr & FLASH_SR_ERROR_MASK) {
|
||||
DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIu32 "\n", sr);
|
||||
DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIx32 "\n", sr);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -452,18 +594,18 @@ static bool stm32l4_cmd_erase(target *t, uint32_t action)
|
||||
stm32l4_flash_unlock(t);
|
||||
/* Erase time is 25 ms. No need for a spinner.*/
|
||||
/* Flash erase action start instruction */
|
||||
target_mem_write32(t, FLASH_CR, action);
|
||||
target_mem_write32(t, FLASH_CR, action | FLASH_CR_STRT);
|
||||
stm32l4_flash_write32(t, FLASH_CR, action);
|
||||
stm32l4_flash_write32(t, FLASH_CR, action | FLASH_CR_STRT);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
if(target_check_error(t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
uint16_t sr = target_mem_read32(t, FLASH_SR);
|
||||
uint16_t sr = stm32l4_flash_read32(t, FLASH_SR);
|
||||
if (sr & FLASH_SR_ERROR_MASK)
|
||||
return false;
|
||||
return true;
|
||||
@ -503,22 +645,22 @@ static bool stm32l4_option_write(
|
||||
{
|
||||
tc_printf(t, "Device will lose connection. Rescan!\n");
|
||||
stm32l4_flash_unlock(t);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
stm32l4_flash_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
stm32l4_flash_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return true;
|
||||
for (int i = 0; i < len; i++)
|
||||
target_mem_write32(t, FPEC_BASE + i2offset[i], values[i]);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_OPTSTRT);
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
target_mem_write32(t, L4_FPEC_BASE + i2offset[i], values[i]);
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OPTSTRT);
|
||||
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return true;
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_OBL_LAUNCH);
|
||||
while (target_mem_read32(t, FLASH_CR) & FLASH_CR_OBL_LAUNCH)
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OBL_LAUNCH);
|
||||
while (stm32l4_flash_read32(t, FLASH_CR) & FLASH_CR_OBL_LAUNCH)
|
||||
if(target_check_error(t))
|
||||
return true;
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_LOCK);
|
||||
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_LOCK);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -540,8 +682,19 @@ static bool stm32l4_option_write(
|
||||
|
||||
static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
|
||||
{
|
||||
if (t->idcode == ID_STM32L55) {
|
||||
tc_printf(t, "STM32L5 options not implemented!\n");
|
||||
return false;
|
||||
}
|
||||
if (t->idcode == ID_STM32WLXX) {
|
||||
tc_printf(t, "STM32WLxx options not implemented!\n");
|
||||
return false;
|
||||
}
|
||||
static const uint32_t g4_values[11] = {
|
||||
0xFFEFF8AA, 0xFFFFFFFF, 0x00FF0000, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FF00,
|
||||
/* SEC_SIZE1 occupies 9 bits on G49/G4A (cat 4),
|
||||
* 8 bits on cat 3 and 7 bits on cat 2.
|
||||
* It is safe to write 0xFF00FE00 (cat 4 value) in FLASH_SEC1R */
|
||||
0xFFEFF8AA, 0xFFFFFFFF, 0x00FF0000, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FE00,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FF00
|
||||
};
|
||||
|
||||
@ -559,6 +712,12 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
|
||||
len = 11;
|
||||
for (int i = 0; i < len; i++)
|
||||
values[i] = g4_values[i];
|
||||
} else if ((t->idcode == ID_STM32G43) || (t->idcode == ID_STM32G49)) {
|
||||
/* G4 cat 2 and 4 (single bank) */
|
||||
i2offset = g4_i2offset;
|
||||
len = 6;
|
||||
for (int i = 0; i < len; i++)
|
||||
values[i] = g4_values[i];
|
||||
} else {
|
||||
len = 9;
|
||||
}
|
||||
@ -569,7 +728,7 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
|
||||
for (i = 2; i < argc; i++)
|
||||
values[i - 2] = strtoul(argv[i], NULL, 0);
|
||||
for (i = i - 2; i < len; i++) {
|
||||
uint32_t addr = FPEC_BASE + i2offset[i];
|
||||
uint32_t addr = L4_FPEC_BASE + i2offset[i];
|
||||
values[i] = target_mem_read32(t, addr);
|
||||
}
|
||||
if ((values[0] & 0xff) == 0xCC) {
|
||||
@ -586,8 +745,8 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i ++) {
|
||||
uint32_t addr = FPEC_BASE + i2offset[i];
|
||||
val = target_mem_read32(t, FPEC_BASE + i2offset[i]);
|
||||
uint32_t addr = L4_FPEC_BASE + i2offset[i];
|
||||
val = target_mem_read32(t, L4_FPEC_BASE + i2offset[i]);
|
||||
tc_printf(t, "0x%08X: 0x%08X\n", addr, val);
|
||||
}
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user