w453509596 发表于 2015-6-14 18:54:24

STM8S的EEPROM块编程问题。

经过小弟的一个周末的努力,终于发现STM8S不能块编程的原因了。首先STM8S的块编程,需要把程序放在RAM中运行。对于像我这样没学过汇编的,也不了解编译器原理的,只知道用C语言写写程序的朋友。有点摸不着头脑。那么如何让程序在RAM中运行呢?
我们看下STM8S的库函数数就知道了。下面是库函数的代码。

IN_RAM(void FLASH_EraseBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType));

我刚开始就被这个函数定义给骗了。以为加了IN_RAM( ),就可以在RAM中运行了。我们看下 IN_RAM() 的定义
#define IN_RAM(a)a
在默认情况下,它什么都没干。仔细一下,在默认情况下,是不库函数把在RAM中运行程序的功能给屏蔽了。

/* Uncomment the line below to enable the FLASH functions execution from RAM */
#if !defined (RAM_EXECUTION)
/*#define RAM_EXECUTION(1) */
#endif /* RAM_EXECUTION */


取消掉这个注释就可以了。把它变成

/* Uncomment the line below to enable the FLASH functions execution from RAM */
#if !defined (RAM_EXECUTION)
   #define RAM_EXECUTION(1)
#endif /* RAM_EXECUTION */


这样IN_RAM()的定义就变成了
#define IN_RAM(a)   __ramfunca

再去调试程序。就好了。

自己写程序其实就是在函数前面加下__ramfunc


下面是我测试成功的程序


uint8_tblock_buff;

__ramfuncvoidWriteBlock(void)
{
uint8_t i;

    FLASH_Unlock(FLASH_MEMTYPE_DATA);
    FLASH->CR2 |= FLASH_CR2_PRG;
    FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NPRG);

for(i=0; i<128; i++)
{
    *((PointerAttr uint8_t*) (MemoryAddressCast)0x4000 + i) = block_buff;
}

   FLASH_Lock(FLASH_MEMTYPE_DATA);
}


祝还不会块编程的朋友们好运!!!!!




但是看门狗我还不知道原因。在接上STLINK调试的时候,看门狗会死机,但是在程序自己运行时,它就正常了








gameng 发表于 2016-9-12 23:43:44

真不错!学习啦

ZHONGLAN 发表于 2016-3-20 22:52:16

学习学习

zcl201207 发表于 2016-3-21 21:40:13

:):):):):)

gavinliang 发表于 2016-9-12 16:45:00

这是因为你在解锁时,是不能设置监控的,你用STLINK调试时,在这里是容易出问题的,一般不作监控。

gavinliang 发表于 2016-9-12 17:00:26

/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
#include "stm8s.h"
#include <stdio.h>
int _fctcpy(char name);
main()
{
u8 block_buff ={0};
u8 i = 0;
u8 c = 0;
_fctcpy('F');

CLK_DeInit();
  CLK_HSICmd(ENABLE);
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);

  UART1_DeInit();
  UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO,
UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENABLE);
  UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
  UART1_Cmd(ENABLE);
  
GPIO_DeInit(GPIOD);
  GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_FAST);

for(i=0;i<128;i++)
   block_buff=i;

  FLASH_DeInit();
  FLASH_Unlock(FLASH_MEMTYPE_DATA);
  FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_TPROG);
  FLASH_ProgramBlock(0x0001, FLASH_MEMTYPE_DATA, FLASH_PROGRAMMODE_STANDARD, block_buff);
FLASH_EraseBlock(0x0001, FLASH_MEMTYPE_DATA);

c = FLASH_ReadByte(0x40ff);//读出值到变量中
printf("c=%x\r\n",(u16)c);//打印
c = FLASH_ReadByte(0x407f);
printf("c=%x\r\n",(u16)c);
c = FLASH_ReadByte(0x4080);
printf("c=%x\r\n",(u16)c);
c = FLASH_ReadByte(0x4100);
printf("c=%x\r\n",(u16)c);

_asm("rim");
while (1)
  {
  GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);
}
}
char putchar (char c)    //串口打印重定向,只要有这个函数,然后包含stdio.h就可以直接调用打印函数了,若有不成功时请把参数前强转为(u16)
{
  if (c == '\n')
  {
    /* put '\r' to hardware here */
    /* Wait transmission is completed : otherwise the first data is not sent */
    while (!(UART1->SR & 0x40));
    UART1->DR = ('\r');
    /* Wait transmission is completed */
    while (!(UART1->SR & 0x40));
}
  /* put c to hardware here */
  /* Wait transmission is completed : otherwise the first data is not sent */
  while (!(UART1->SR & 0x80));
  UART1->DR = (c);
  /* Wait transmission is completed */
  while (!(UART1->SR & 0x80));
  return (c);
}

gavinliang 发表于 2016-9-12 17:01:49

用Cosmic编译,使用ST库函数,已经调试通过,供大家参考一下。:lol

gavinliang 发表于 2016-9-12 17:03:20

//用Cosmic编译,使用ST库函数,已经调试通过,供大家参考一下。
/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
#include "stm8s.h"
#include <stdio.h>
int _fctcpy(char name);
main()
{
u8 block_buff ={0};
u8 i = 0;
u8 c = 0;
_fctcpy('F');

CLK_DeInit();
  CLK_HSICmd(ENABLE);
CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);

  UART1_DeInit();
  UART1_Init((u32)115200, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO,
UART1_SYNCMODE_CLOCK_DISABLE,UART1_MODE_TXRX_ENABLE);
  UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
  UART1_Cmd(ENABLE);
  
GPIO_DeInit(GPIOD);
  GPIO_Init(GPIOD, GPIO_PIN_LNIB, GPIO_MODE_OUT_PP_LOW_FAST);

for(i=0;i<128;i++)
   block_buff=i;

  FLASH_DeInit();
  FLASH_Unlock(FLASH_MEMTYPE_DATA);
  FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_TPROG);
  FLASH_ProgramBlock(0x0001, FLASH_MEMTYPE_DATA, FLASH_PROGRAMMODE_STANDARD, block_buff);
FLASH_EraseBlock(0x0001, FLASH_MEMTYPE_DATA);

c = FLASH_ReadByte(0x40ff);//读出值到变量中
printf("c=%x\r\n",(u16)c);//打印
c = FLASH_ReadByte(0x407f);
printf("c=%x\r\n",(u16)c);
c = FLASH_ReadByte(0x4080);
printf("c=%x\r\n",(u16)c);
c = FLASH_ReadByte(0x4100);
printf("c=%x\r\n",(u16)c);

_asm("rim");
while (1)
  {
  GPIO_WriteHigh(GPIOD, GPIO_PIN_LNIB);
}
}
char putchar (char c)    //串口打印重定向,只要有这个函数,然后包含stdio.h就可以直接调用打印函数了,若有不成功时请把参数前强转为(u16)
{
  if (c == '\n')
  {
    /* put '\r' to hardware here */
    /* Wait transmission is completed : otherwise the first data is not sent */
    while (!(UART1->SR & 0x40));
    UART1->DR = ('\r');
    /* Wait transmission is completed */
    while (!(UART1->SR & 0x40));
}
  /* put c to hardware here */
  /* Wait transmission is completed : otherwise the first data is not sent */
  while (!(UART1->SR & 0x80));
  UART1->DR = (c);
  /* Wait transmission is completed */
  while (!(UART1->SR & 0x80));
  return (c);
}

gavinliang 发表于 2016-9-12 17:09:22

另:两把密钥的顺序不是随便的,解锁eeprom时顺序是0xae,0x56,解锁flash时顺序是0x56,0xae,我见过网上有人说顺序不分的,纠正下,不要误人子弟!顺序出错是了怎么都出不来的,ST英文原文写得很清楚了,有些翻译就是翻译错了,大家注意一下。

gavinliang 发表于 2016-9-12 17:14:05

再贴上ST公司调用库文件的例子,供参考:
/**
******************************************************************************
* @file   FLASH/FLASH_DataProgram/main.c
* @author   MCD Application Team
* @versionV2.2.0
* @date   30-September-2014
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
*
* 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.
*
******************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stm8s_eval.h"

/**
* @addtogroup FLASH_DataProgram
* @{
*/

/* Private typedef -----------------------------------------------------------*/
typedef enum { FAILED = 0, PASSED = !FAILED} TestStatus;
/* Private define ------------------------------------------------------------*/
#define BLOCK_OPERATION    0    /* block 0 in data eeprom memory: address is 0x4000 */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t GBuffer;
__IO TestStatus OperationStatus;

#ifdef _RAISONANCE_
/* needed by memcpy for raisonance */
#include <string.h>
extern int __address__FLASH_EraseBlock;
extern int __size__FLASH_EraseBlock;
extern int __address__FLASH_ProgramBlock;
extern int __size__FLASH_ProgramBlock;
#endif /*_RAISONANCE_*/

/* Private function prototypes -----------------------------------------------*/
/* Declare _fctcpy function prototype as it is packaged by default in the Cosmic
   machine library */
#ifdef _COSMIC_
int _fctcpy(char name);
#endif /*_COSMIC_*/

void Delay (uint16_t nCount);
static void CLK_Config(void);
static void GPIO_Config(void);
static void FLASH_Config(void);
/* Private functions ---------------------------------------------------------*/

/**
* @briefMain program.
* @paramNone
* @retval None
*/
void main(void)
{
uint32_t add = 0, startadd = 0, stopadd = 0;
uint8_t newval = 0xAA;
uint8_t i = 0;

#ifdef _COSMIC_
/* Call the _fctcpy() function with the first segment character as parameter
   "_fctcpy('F');"for a manual copy of the declared moveable code segment
   (FLASH_CODE) in RAM before execution*/
_fctcpy('F');
#endif /*_COSMIC_*/

#ifdef _RAISONANCE_
/* Call the standard C library: memcpy() or fmemcpy() functions available through
   the <string.h> to copy the inram function to the RAM destination address */
MEMCPY(FLASH_EraseBlock,
         (void PointerAttr*)&__address__FLASH_EraseBlock,
         (int)&__size__FLASH_EraseBlock);
MEMCPY(FLASH_ProgramBlock,
         (void PointerAttr*)&__address__FLASH_ProgramBlock,
         (int)&__size__FLASH_ProgramBlock);
#endif /*_RAISONANCE_*/


/* Clock configuration -----------------------------------------*/
CLK_Config();

/* GPIO Configuration ------------------------------------------*/
GPIO_Config();

/* FLASH Configuration ------------------------------------------*/
FLASH_Config();

/* Fill the buffer in RAM */
for (i = 0; i < FLASH_BLOCK_SIZE; i++)
{
    GBuffer = newval;
}
/* This function is executed from RAM */
FLASH_ProgramBlock(BLOCK_OPERATION, FLASH_MEMTYPE_DATA, FLASH_PROGRAMMODE_STANDARD, GBuffer);

/* Wait until End of high voltage flag is set*/
while (FLASH_GetFlagStatus(FLASH_FLAG_HVOFF) == RESET)
{}
/* Check the programmed block */
startadd = FLASH_DATA_START_PHYSICAL_ADDRESS + ((uint16_t)BLOCK_OPERATION * (uint16_t)FLASH_BLOCK_SIZE);
stopadd = startadd + (uint16_t)FLASH_BLOCK_SIZE;
for (add = startadd; add < stopadd; add++)
      {
      if (FLASH_ReadByte(add) != newval)
      {
          /* Error */
          OperationStatus = FAILED;
          /* OperationStatus = PASSED, if the data written/read to/from Flash program memory is correct */
          /* OperationStatus = FAILED, if the data written/read to/from Flash program memory is corrupted */
          while (1)
          {
            STM_EVAL_LEDToggle(LED1); /*FAIL: write error */
            Delay(0xFFFF);
          }
      }
      }
/* Erase block 0 and verify it */
/* This function is executed from RAM */
FLASH_EraseBlock(BLOCK_OPERATION, FLASH_MEMTYPE_DATA);

/* Wait until End of high voltage flag is set*/
while (FLASH_GetFlagStatus(FLASH_FLAG_HVOFF) == RESET)
{}

for (add = startadd; add < stopadd; add++)
      {
      if (FLASH_ReadByte(add) != 0x00)
      {
          /* Error */
          OperationStatus = FAILED;
          /* OperationStatus = PASSED, if the data written/read to/from Flash program memory is correct */
          /* OperationStatus = FAILED, if the data written/read to/from Flash program memory is corrupted */
          while (1)
          {
            STM_EVAL_LEDToggle(LED2); /* FAIL: Erase error */
            Delay(0xFFFF);
          }
      }
      }

/* Pass */
OperationStatus = PASSED;
/* OperationStatus = PASSED, if the data written/read to/from Flash program memory is correct */
/* OperationStatus = FAILED, if the data written/read to/from Flash program memory is corrupted */
while (1)
{
    STM_EVAL_LEDToggle(LED3); /* PASS: without errors*/
    Delay(0xFFFF);
}
}

/**
* @briefConfigure system clock to run at 16Mhz
* @paramNone
* @retval None
*/
void CLK_Config(void)
{
    /* Initialization of the clock */
    /* Clock divider to HSI/1 */
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
}

/**
* @briefConfigure GPIO for LEDs available on the evaluation board
* @paramNone
* @retval None
*/
void GPIO_Config(void)
{
    /* Initialize LEDs mounted on STM8-128 EVAL board */
    STM_EVAL_LEDInit(LED2);
    STM_EVAL_LEDInit(LED3);
    STM_EVAL_LEDInit(LED1);
               
                /* All leds are Off */
    STM_EVAL_LEDOff(LED2);
    STM_EVAL_LEDOff(LED3);
    STM_EVAL_LEDOff(LED1);
}

/**
* @briefConfigure the FLASH for block programming
* @paramNone
* @retval None
*/
void FLASH_Config(void)
{
/* Define flash programming Time*/
FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);

FLASH_Unlock(FLASH_MEMTYPE_PROG);
/* Wait until Flash Program area unlocked flag is set*/
while (FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET)
{}

/* Unlock flash data eeprom memory */
FLASH_Unlock(FLASH_MEMTYPE_DATA);
/* Wait until Data EEPROM area unlocked flag is set*/
while (FLASH_GetFlagStatus(FLASH_FLAG_DUL) == RESET)
{}
}

/**
* @briefDelay.
* @paramnCount
* @retval None
*/
void Delay(uint16_t nCount)
{
    /* Decrement nCount value */
    while (nCount != 0)
    {
      nCount--;
    }
}

#ifdefUSE_FULL_ASSERT
/**
* @briefReports the name of the source file and the source line number
*   where the assert_param error has occurred.
* @paramfile: pointer to the source file name
* @paramline: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
   ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */
while (1)
{}
}
#endif

/**
* @}
*/

/**
* @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
页: [1] 2
查看完整版本: STM8S的EEPROM块编程问题。