Тогда моргать диодом -
длинная пауза
моргаем десятки
короткая пауза
моргаем единицы
открыть STM32CubeProgrammer в режиме CLI ,подсоедениться к чипу через ST-LInk , найти границу памяти ОЗУ попытакми напряму писать в адреса памяти, до тех пор ,пока не зависнет или вернеться какой то error
ну или перепрошить st-link в j-link и делать то же самое через коммандную строку в J-Flash или J-LinkGDBCLI или типа того
набросал пример
Спойлер
/**
******************************************************************************
* @file : main.c
* @author : Auto-generated by STM32CubeIDE
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
//#include <stdint.h>
#include "stm32f10x.h"
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
int main(void) {
__IO int StartUpCounter;
////////////////////////////////////////////////////////////
//Запускаем кварцевый генератор
////////////////////////////////////////////////////////////
RCC->CR |= RCC_CR_HSEON; //Запускаем генератор HSE
//Ждем успешного запуска или окончания тайм-аута
for(StartUpCounter=0; ; StartUpCounter++) {
//Если успешно запустилось, то
//выходим из цикла
if (RCC->CR & RCC_CR_HSERDY) break;
//Если не запустилось, то
//отключаем все, что включили
//и возвращаем ошибку
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
return 1;
}
}
////////////////////////////////////////////////////////////
//Настраиваем и запускаем PLL
////////////////////////////////////////////////////////////
//Настраиваем PLL
RCC->CFGR |= RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLMULL_1 | RCC_CFGR_PLLMULL_2; //PLL множитель равен 9 // 0111: PLL input clock x 9
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE; //Тактирование PLL от HSE
RCC->CR |= RCC_CR_PLLON; //Запускаем PLL
//Ждем успешного запуска или окончания тайм-аута
for(StartUpCounter=0; ; StartUpCounter++) {
//Если успешно запустилось, то
//выходим из цикла
if (RCC->CR & RCC_CR_PLLRDY) break;
//Если по каким-то причинам не запустился PLL, то
//отключаем все, что включили
//и возвращаем ошибку
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
RCC->CR &= ~RCC_CR_PLLON; //Останавливаем PLL
return 2;
}
}
////////////////////////////////////////////////////////////
//Настраиваем FLASH и делители
////////////////////////////////////////////////////////////
//Устанавливаем 2 цикла ожидания для Flash
//так как частота ядра у нас будет 48 MHz < SYSCLK <= 72 MHz
FLASH->ACR |= FLASH_ACR_LATENCY_1; // 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
//Делители
RCC->CFGR &= ~RCC_CFGR_PPRE2; //Делитель шины APB2 отключен // 0xx: HCLK not divided
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; //Делитель нишы APB1 равен 2 // 100: HCLK divided by 2
RCC->CFGR &= ~RCC_CFGR_HPRE; //Делитель AHB отключен // 0xxx: SYSCLK not divided
RCC->CFGR &= ~RCC_CFGR_SW; //Переключаемся на работу от PLL // 10: PLL selected as system clock
RCC->CFGR |= RCC_CFGR_SW_1; //Переключаемся на работу от PLL // 10: PLL selected as system clock
//Ждем, пока переключимся
while(!(RCC->CFGR & RCC_CFGR_SWS_1));
//После того, как переключились на
//внешний источник такирования
//отключаем внутренний RC-генератор
//для экономии энергии
//RCC->CR &= ~RCC_CR_HSION; // При отключенном HSI Или его частоте выше 24 МГц не работает запись/стирание FLASH пользовательской памяти!!!
//Настройка и переклбючение сисемы
//на внешний кварцевый генератор
//и PLL запершилось успехом.
//Выходим
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // GPIO port C
GPIOC->CRH &= ~GPIO_CRH_MODE13; // 00: Input mode (reset state)
GPIOC->CRH |= GPIO_CRH_MODE13_0; // 01: Output mode, max speed 10 MHz.
GPIOC->CRH &= ~GPIO_CRH_CNF13; // 00: General purpose output push-pull
GPIOC->BSRR |= GPIO_BSRR_BS13; // PC13 HIGH LED OFF
#define magic_byte ((unsigned char)0xC6)
#define max_sram_adr ((unsigned long)20*1024)
#define test_ram_adr ((unsigned long)max_sram_adr-4)
*((unsigned char *)test_ram_adr) = magic_byte;
if ((*((unsigned char *)test_ram_adr)) == magic_byte) {
GPIOC->BSRR |= GPIO_BSRR_BR13; // PC13 LOW LED ON
}
return 0;
}
102 строка не отрабатывает
или запись ниже максимальной границы даже не работает или я что то не так написал
так оно в ассемблере выглядит
if ((*((unsigned char *)test_ram_adr)) == magic_byte) {
80002b0: f644 73fc movw r3, #20476 ; 0x4ffc
80002b4: 781b ldrb r3, [r3, #0]
80002b6: 2bc6 cmp r3, #198 ; 0xc6
80002b8: d105 bne.n 80002c6 <main+0x156>
GPIOC->BSRR |= GPIO_BSRR_BR13; // PC13 LOW LED ON
80002ba: 4b08 ldr r3, [pc, #32] ; (80002dc <main+0x16c>)
80002bc: 691b ldr r3, [r3, #16]
80002be: 4a07 ldr r2, [pc, #28] ; (80002dc <main+0x16c>)
80002c0: f043 5300 orr.w r3, r3, #536870912 ; 0x20000000
80002c4: 6113 str r3, [r2, #16]
}
адрес начала 0х02000000 + test_ram_adr
Вы не туда стучитесь !
0x20005000-4, а не 0x5000-4
да, забыл что не с нуля память идет.
в итоге: ниже макс границы - работает, выше - не работает.
Спойлер
#include "stm32f10x.h"
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
int main(void) {
__IO int StartUpCounter;
RCC->CR |= RCC_CR_HSEON; //Запускаем генератор HSE
for(StartUpCounter=0; ; StartUpCounter++) {
if (RCC->CR & RCC_CR_HSERDY) break;
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
return 1;
}
}
RCC->CFGR |= RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLMULL_1 | RCC_CFGR_PLLMULL_2; //PLL множитель равен 9 // 0111: PLL input clock x 9
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE; //Тактирование PLL от HSE
RCC->CR |= RCC_CR_PLLON; //Запускаем PLL
for(StartUpCounter=0; ; StartUpCounter++) {
if (RCC->CR & RCC_CR_PLLRDY) break;
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
RCC->CR &= ~RCC_CR_PLLON; //Останавливаем PLL
return 2;
}
}
FLASH->ACR |= FLASH_ACR_LATENCY_1; // 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
RCC->CFGR &= ~RCC_CFGR_PPRE2; //Делитель шины APB2 отключен // 0xx: HCLK not divided
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; //Делитель нишы APB1 равен 2 // 100: HCLK divided by 2
RCC->CFGR &= ~RCC_CFGR_HPRE; //Делитель AHB отключен // 0xxx: SYSCLK not divided
RCC->CFGR &= ~RCC_CFGR_SW; //Переключаемся на работу от PLL // 10: PLL selected as system clock
RCC->CFGR |= RCC_CFGR_SW_1; //Переключаемся на работу от PLL // 10: PLL selected as system clock
while(!(RCC->CFGR & RCC_CFGR_SWS_1));
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // GPIO port C
GPIOC->CRH &= ~GPIO_CRH_MODE13; // 00: Input mode (reset state)
GPIOC->CRH |= GPIO_CRH_MODE13_0; // 01: Output mode, max speed 10 MHz.
GPIOC->CRH &= ~GPIO_CRH_CNF13; // 00: General purpose output push-pull
GPIOC->BSRR |= GPIO_BSRR_BS13; // PC13 HIGH LED OFF
#define magic_byte ((unsigned char)0xC6)
#define max_sram_adr ((unsigned long)20*1024+0x20000000)
#define test_ram_adr ((unsigned long)max_sram_adr-4)
unsigned char * ptrB = (unsigned char *) test_ram_adr;
*ptrB = magic_byte;
if (*ptrB == magic_byte) {
GPIOC->BSRR |= GPIO_BSRR_BR13; // PC13 LOW LED ON
}
return 0;
}
Следовательно 20К…
А зачем для того что бы моргнуть диодом разгонять HSE и PLL ?
А с флеш не соответствует …
а этого мы точно не знаем , так как писать везде не пытались
я даже не сомневался
ну а FLASH проверяется тупо в ST Link Utility
вру, не дает он прыгнцть выше потолка, сейчас попробую программу состряпать
в моем МК 512 страниц флэша по 128 байт
511 ый записался без проблем
Спойлер
#include "stm32f10x.h"
#if !defined(__SOFT_FP__) && defined(__ARM_FP)
#warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
#endif
#define NVIC_VectTab_FLASH ((unsigned long)0x08000000) // начало флэша
#define FLASH_PAGE_SIZE ((unsigned long)128) // CHF32F103C8T6 -> 128 // размер одной страницы // размер страницы памяти для большинства МК серии STM32F103 составляет 1Kb, за исключением микроконтроллеров линейки HD и CL (Connectivity Line), в которых она равна двум килобайтам
#define NUM_PAGE_EEPROM_BEGIN ((unsigned long)511) // с какой страницы памяти будем писать свои данные // 256*128=0x8000->0x8008000
#define FIRMWARE_PAGE_OFFSET ((unsigned long)NUM_PAGE_EEPROM_BEGIN*FLASH_PAGE_SIZE) // смещение в байтах, с которого будем писать свои данные
unsigned long FLASH_read(uint32_t address) {
return (*(__IO uint32_t*) address);
}
#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)
void FLASH_Unlock(void) {
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
void FLASH_Lock() {
FLASH->CR |= FLASH_CR_LOCK;
}
void FLASH_ErasePage(unsigned long inAdr) {
FLASH->CR |= FLASH_CR_PER; //Устанавливаем бит стирания одной страницы
FLASH->AR = inAdr; // Задаем её адрес
FLASH->CR |= FLASH_CR_STRT; // Запускаем стирание
while ((FLASH->SR & FLASH_SR_BSY) != 0 ); // Wait end of eraze
FLASH->CR &= ~FLASH_CR_PER; //Сбрасываем бит обратно
}
void FLASH_fill_page(uint32_t Value) {
uint32_t pageAdr = NVIC_VectTab_FLASH + FIRMWARE_PAGE_OFFSET; // Адрес страницы памяти
FLASH_Unlock(); // Разблокируем память для записи
FLASH_ErasePage(pageAdr); // Очистим страницу памяти
FLASH->CR |= FLASH_CR_PG; //Разрешаем программирование флеша
for(unsigned short i = 0; i < (FLASH_PAGE_SIZE/4); ++i) {
unsigned long inValue = Value;
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
*(__IO uint16_t*)pageAdr = (uint16_t)inValue; //Пишем младшие 2 бата
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
pageAdr += 2;
inValue>>=16;
*(__IO uint16_t*)pageAdr = (uint16_t)inValue; //Пишем старшие 2 байта
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
pageAdr += 2;
}
FLASH->CR &= ~FLASH_CR_PG; //Запрещаем программирование флеша
FLASH_Lock();
}
void FLASH_write_param(unsigned short numParam, uint32_t paramValue) {
uint32_t pageAdr = NVIC_VectTab_FLASH + FIRMWARE_PAGE_OFFSET; // Адрес страницы памяти
numParam %= FLASH_PAGE_SIZE/4; // номер параметра не может превысить число 4х байтовых слов в странице
unsigned long dataPage[FLASH_PAGE_SIZE/4]; // место куда сохраним текущую страницу
for(unsigned short i = 0; i < (FLASH_PAGE_SIZE/4); ++i) dataPage[i] = FLASH_read(pageAdr + i * 4);
dataPage[numParam] = paramValue;
FLASH_Unlock(); // Разблокируем память для записи
FLASH_ErasePage(pageAdr); // Очистим страницу памяти
FLASH->CR |= FLASH_CR_PG; //Разрешаем программирование флеша
for(unsigned short i = 0; i < (FLASH_PAGE_SIZE/4); ++i) {
unsigned long inValue = dataPage[i];
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
*(__IO uint16_t*)pageAdr = (uint16_t)inValue; //Пишем младшие 2 бата
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
pageAdr += 2;
inValue>>=16;
*(__IO uint16_t*)pageAdr = (uint16_t)inValue; //Пишем старшие 2 байта
while ((FLASH->SR & FLASH_SR_BSY) != 0 );
pageAdr += 2;
}
FLASH->CR &= ~FLASH_CR_PG; //Запрещаем программирование флеша
FLASH_Lock();
}
unsigned long FLASH_read_param(unsigned short numParam) {
uint32_t pageAdr = NVIC_VectTab_FLASH + FIRMWARE_PAGE_OFFSET; // Адрес страницы памяти
numParam %= FLASH_PAGE_SIZE/4; // номер параметра не может превысить число 4х байтовых слов в странице
return FLASH_read(pageAdr + numParam * 4);
}
int main(void) {
__IO int StartUpCounter;
RCC->CR |= RCC_CR_HSEON; //Запускаем генератор HSE
for(StartUpCounter=0; ; StartUpCounter++) {
if (RCC->CR & RCC_CR_HSERDY) break;
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
return 1;
}
}
RCC->CFGR |= RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLMULL_1 | RCC_CFGR_PLLMULL_2; //PLL множитель равен 9 // 0111: PLL input clock x 9
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE; //Тактирование PLL от HSE
RCC->CR |= RCC_CR_PLLON; //Запускаем PLL
for(StartUpCounter=0; ; StartUpCounter++) {
if (RCC->CR & RCC_CR_PLLRDY) break;
if (StartUpCounter > 0x1000) {
RCC->CR &= ~RCC_CR_HSEON; //Останавливаем HSE
RCC->CR &= ~RCC_CR_PLLON; //Останавливаем PLL
return 2;
}
}
FLASH->ACR |= FLASH_ACR_LATENCY_1; // 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
RCC->CFGR &= ~RCC_CFGR_PPRE2; //Делитель шины APB2 отключен // 0xx: HCLK not divided
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; //Делитель нишы APB1 равен 2 // 100: HCLK divided by 2
RCC->CFGR &= ~RCC_CFGR_HPRE; //Делитель AHB отключен // 0xxx: SYSCLK not divided
RCC->CFGR &= ~RCC_CFGR_SW; //Переключаемся на работу от PLL // 10: PLL selected as system clock
RCC->CFGR |= RCC_CFGR_SW_1; //Переключаемся на работу от PLL // 10: PLL selected as system clock
while(!(RCC->CFGR & RCC_CFGR_SWS_1));
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // GPIO port C
GPIOC->CRH &= ~GPIO_CRH_MODE13; // 00: Input mode (reset state)
GPIOC->CRH |= GPIO_CRH_MODE13_0; // 01: Output mode, max speed 10 MHz.
GPIOC->CRH &= ~GPIO_CRH_CNF13; // 00: General purpose output push-pull
GPIOC->BSRR |= GPIO_BSRR_BS13; // PC13 HIGH LED OFF
/*#define magic_byte ((unsigned char)0xC6)
#define max_sram_adr ((unsigned long)20*1024+0x20000000)
#define test_ram_adr ((unsigned long)max_sram_adr-4)
unsigned char * ptrB = (unsigned char *) test_ram_adr;
*ptrB = magic_byte;
if (*ptrB == magic_byte) {
GPIOC->BSRR |= GPIO_BSRR_BR13; // PC13 LOW LED ON
}*/
FLASH_write_param(8, 0x12345678);
unsigned long testParam = FLASH_read_param(8);
testParam += 0x20;
FLASH_write_param(11, testParam);
GPIOC->BSRR |= GPIO_BSRR_BR13; // PC13 LOW LED ON
return 0;
}
сейчас попробую 512ый записать и проверить результат
нет, китайцы лишнего не доложили
МК наглухо завис.
А зачем?
Что, Си не позволяет записать в указатель произвольное число, а потом попытаться осуществить чтение/запись по этому указателю?
это делал чтоб стэк сдвинуть на верхную границу памяти (как оказалось несуществующей)
Кстати, очень удивлен - в чем смысл? Мои “синие таблетки” дешевле твоих чуть-ли не в 1,5 раза, а ресурсов больше наклали )))
смысл что не доложили?
или что? не понял вопроса.
вам же было любопытно лишнюю память помотреть, мне оно не надо
просто оттестировали механизм проверки…
Лень обрезать готовую функцию инициализации.