打印
[应用相关]

STM8S 脱机烧写器的开源代码下载转帖

[复制链接]
2338|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Ryze|  楼主 | 2017-5-25 20:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM8S 脱机烧写器的开源代码下载转帖

脱机烧写器的开源代码.rar

759.89 KB

沙发
xixi2017| | 2017-5-25 21:04 | 只看该作者
/*******************************************************************************
项目: STM8S系列脱机烧写
4合一,4CPU结构,主控制芯片为STM32F103C8T6
总编程按钮, 与目标芯片采用SWIM通讯方式
USBHID部分来源于ST官方范例改造,USB库版本V3.1.0
SWIM通讯部分来源于Versaloon开源项目,在此感谢
整个的烧写流程: PC下载STM8S目标程序的镜像代码到stm32C8T6内部空余的flash空间,
然后脱机按钮执行提取stm32F103C8T6的芯片镜像数据,烧写到STM8S芯片中
目前测试都是基于STM8S103F3P6芯片,测试烧写8K flash
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"                                   //此文件引用stm32f10x_conf.h中指定要包含的系统头文件
#include "usb_lib.h"
#include "hw_config.h"
#include "platform_config.h"

#define VarStartAddr        0x08006000                                //定义空余的Flash空间起始地址
#define SWIM_MAX_DLY                                        0xFFFFF
#define SWIM_MAX_RESEND_CNT                                20

#define SWIM_CMD_BITLEN                                        3
#define SWIM_CMD_SRST                                        0x00         //复位
#define SWIM_CMD_ROTF                                        0x01         //SWIM 飞速读
#define SWIM_CMD_WOTF                                        0x02         //SWIM 飞速写

#define SWIM_SYNC_CYCLES                                128

ErrorStatus  HSEStartUpStatus;
FLASH_Status FlashStatus;
TIM_TimeBaseInitTypeDef        TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;

void Tim4_config(void);

union u32Tou8
{
        vu32 ulongx;
        vu16 u16x[2];
        vu8  u8x[4];
};
union u32Tou8 tmpVar;

static uint32_t VarAddr;
static uint8_t SWIM_Inited ;
uint8_t RecCmdFlag;
uint8_t Receive_Buffer[256];
uint8_t Transceive_Buffer[256];
u16 SWIM_SYNC_CNT;

static u16 SWIM_PULSE_0;
static u16 SWIM_PULSE_1;
static u16 SWIM_PULSE_Threshold;
static u16 SWIM_DMA_IN_Buffer[12];
static u16 SWIM_DMA_OUT_Buffer[12];
static uint16_t SWIM_clock_div = 0;
static uint8_t ReadBuff[64];
static uint8_t WriteBuff[64];
static uint8_t cmdrtv;

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void Delay(__IO uint32_t nCount);
void Delay_uS(u16 nus);
void Delay_mS(u16 nms);
void RTC_Configuration(void);
void Tim2_Pwm_config(void);
void Tim2_config(void);
void Tim3_config(void);
/* Private functions ---------------------------------------------------------*/



static void SWIM_Init()
{
        if (!SWIM_Inited)
        {
                SWIM_Inited = 1;
                SYNCSWPWM_OUT_TIMER_INIT(0);
                SYNCSWPWM_PORT_OD_INIT();                //端口切换到第二功能输出口
        }
}

static void SWIM_Fini()
{
        SYNCSWPWM_PORT_ODPP_FINI();
        SYNCSWPWM_OUT_TIMER_FINI();
        SYNCSWPWM_IN_TIMER_FINI();
        SWIM_Inited = 0;
}

static void SWIM_EnableClockInput(void)
{
        SWIM_clock_div = 0;
        SYNCSWPWM_IN_TIMER_INIT();
}


static uint8_t SWIM_EnterProgMode(void)
{
        uint8_t i;
        uint32_t dly;
        SYNCSWPWM_IN_TIMER_RISE_DMA_INIT(10, SWIM_DMA_IN_Buffer);                         //分配DMA存储空间
        SWIM_LOW();
        Delay_uS(1000);
        for (i = 0; i < 4; i++)
        {
                SWIM_HIGH();
                Delay_uS(500);
                SWIM_LOW();
                Delay_uS(500);
        }
        for (i = 0; i < 4; i++)
        {
                SWIM_HIGH();
                Delay_uS(250);
                SWIM_LOW();
                Delay_uS(250);
        }
        SWIM_HIGH();
        dly = SWIM_MAX_DLY;
        SYNCSWPWM_IN_TIMER_RISE_DMA_WAIT(dly);
        if (!dly)
        {
                return 1;
        }
        else
        {
                return 0;
        }
}




//设置SWIM通讯时钟参数
//默认SWIM时钟为HSI/2=8MHz,周期=0.125us x 22拍 =2.75us
static uint8_t SWIM_SetClockParam(uint8_t mHz, uint8_t cnt0, uint8_t cnt1)
{
        uint16_t clock_div;
       
        if (SWIM_clock_div)
        {
                clock_div = SWIM_clock_div;
        }
        else
        {
                clock_div = SYNCSWPWM_OUT_TIMER_MHZ / mHz;                       
                if ((SYNCSWPWM_OUT_TIMER_MHZ % mHz) >= (mHz / 2))       
                {
                        clock_div++;
                }
                clock_div *= SWIM_SYNC_CYCLES;                                                        //9x128=1152
        }

        SWIM_PULSE_0 = cnt0 * clock_div / SWIM_SYNC_CYCLES;
        if ((cnt0 * clock_div % SWIM_SYNC_CYCLES) >= SWIM_SYNC_CYCLES / 2)
        {
                SWIM_PULSE_0++;
        }
        SWIM_PULSE_1 = cnt1 * clock_div / SWIM_SYNC_CYCLES;
        if ((cnt1 * clock_div % SWIM_SYNC_CYCLES) >= SWIM_SYNC_CYCLES / 2)
        {
                SWIM_PULSE_1++;
        }
        SWIM_PULSE_Threshold = SWIM_PULSE_0 + SWIM_PULSE_1;

        // 1.125 times
        //SYNCSWPWM_OUT_TIMER_SetCycle(SWIM_PULSE_Threshold + (SWIM_PULSE_Threshold >> 3));
        SYNCSWPWM_OUT_TIMER_SetCycle(SWIM_PULSE_Threshold);
        SWIM_PULSE_Threshold >>= 1;
        return 0;
}


static u8 SWIM_HW_Out(u8 cmd, u8 bitlen, u16 retry_cnt)
{
        int8_t i, p;
        u32 dly;
        u16 *ptr = &SWIM_DMA_OUT_Buffer[0];

retry:

        SYNCSWPWM_IN_TIMER_RISE_DMA_INIT(bitlen + 3, SWIM_DMA_IN_Buffer);

        *ptr++ = SWIM_PULSE_0;

        p = 0;
        for (i = bitlen - 1; i>=0; i--)
        {
                if ((cmd >> i) & 1)
                {
                        *ptr++ = SWIM_PULSE_1;
                        p++;
                }
                else
                {
                        *ptr++ = SWIM_PULSE_0;
                }
        }
        // parity bit
        if (p & 1)
        {
                *ptr++ = SWIM_PULSE_1;
        }
        else
        {
                *ptr++ = SWIM_PULSE_0;
        }
        // wait for last waveform -- parity bit
        *ptr++ = 0;
        SYNCSWPWM_OUT_TIMER_DMA_INIT(bitlen + 3, SWIM_DMA_OUT_Buffer);
        SYNCSWPWM_OUT_TIMER_DMA_WAIT();

        dly = SWIM_MAX_DLY;
        SYNCSWPWM_IN_TIMER_RISE_DMA_WAIT(dly);
        SYNCSWPWM_IN_TIMER_RISE_DMA_INIT(10, SWIM_DMA_IN_Buffer + 1);

        if (!dly)
        {
                // timeout
                return 2;
        }
        else if (SWIM_DMA_IN_Buffer[bitlen + 2] > SWIM_PULSE_Threshold)                 //判断最后一个ACK应答是否为"1",小于半个周期的低电平在前
        {
                // nack       
                if (retry_cnt)
                {
                        retry_cnt--;
                        goto retry;
                }
                else
                {
                        return 1;
                }
        }
        else
        {
                return 0;
        }
}


static u8 SWIM_HW_In(u8* data, u8 bitlen)
{
        u8 ret = 0;
        u32 dly;

        dly = SWIM_MAX_DLY;
        SYNCSWPWM_IN_TIMER_RISE_DMA_WAIT(dly);                                                                        //先接收引导bit,目标到主机,这个位必须是1
        *data = 0;
        if (dly && (SWIM_DMA_IN_Buffer[1] < SWIM_PULSE_Threshold))                                //如果=1,低电平时间小于4个脉冲
        {
                for (dly = 0; dly < 8; dly++)
                {
                        if (SWIM_DMA_IN_Buffer[2 + dly] < SWIM_PULSE_Threshold)                                                       
                        {
                                *data |= 1 << (7 - dly);
                        }
                }
                SYNCSWPWM_IN_TIMER_RISE_DMA_INIT(11, SWIM_DMA_IN_Buffer);

                SWIM_DMA_OUT_Buffer[0] = SWIM_PULSE_1;
                SWIM_DMA_OUT_Buffer[1] = 0;
                SYNCSWPWM_OUT_TIMER_DMA_INIT(2, SWIM_DMA_OUT_Buffer);
                SYNCSWPWM_OUT_TIMER_DMA_WAIT();
        }
        else
        {
                ret = 1;
        }

        return ret;
}


static uint8_t SWIM_SRST(void)
{
        return SWIM_HW_Out(SWIM_CMD_SRST, SWIM_CMD_BITLEN, SWIM_MAX_RESEND_CNT);
}

static uint8_t SWIM_WOTF(uint32_t addr, uint16_t len, uint8_t *data)
{
        uint16_t processed_len;
        uint8_t cur_len, i;
        uint32_t cur_addr, addr_tmp;
        u8 rtv2;

        if ((0 == len) || ((uint8_t*)0 == data))
        {
                return 1;
        }

        processed_len = 0;
        cur_addr = addr;
        while (processed_len < len)
        {
                if ((len - processed_len) > 255)
                {
                        cur_len = 255;
                }
                else
                {
                        cur_len = len - processed_len;
                }

                SET_LE_U32(&addr_tmp, cur_addr);

                if(SWIM_HW_Out(SWIM_CMD_WOTF, SWIM_CMD_BITLEN, SWIM_MAX_RESEND_CNT))
                {
                        return 1;
                }
                if (SWIM_HW_Out(cur_len, 8, 0))
                {
                        return 2;
                }
                rtv2=SWIM_HW_Out((addr_tmp >> 16) & 0xFF, 8, 0);         //retry=0,出错后不重发
                if (rtv2)
                {
                        return 3;
                }
                if (SWIM_HW_Out((addr_tmp >> 8) & 0xFF, 8, 0))
                {
                        return 4;
                }
                if (SWIM_HW_Out((addr_tmp >> 0) & 0xFF, 8, 0))
                {
                        return 5;
                }
                for (i = 0; i < cur_len; i++)
                {
                        if (SWIM_HW_Out(data[processed_len + i], 8, SWIM_MAX_RESEND_CNT))
                        {
                                return 6;
                        }
                }

                cur_addr += cur_len;
                processed_len += cur_len;
        }

        return 0;
}

static uint8_t SWIM_ROTF(uint32_t addr, uint16_t len, uint8_t *data)
{
        uint16_t processed_len;
        uint8_t cur_len, i;
        uint32_t cur_addr, addr_tmp;

        if ((0 == len) || ((uint8_t*)0 == data))
        {
                return 7;
        }

        processed_len = 0;
        cur_addr = addr;
        while (processed_len < len)
        {
                if ((len - processed_len) > 255)
                {
                        cur_len = 255;
                }
                else
                {
                        cur_len = len - processed_len;
                }

                SET_LE_U32(&addr_tmp, cur_addr);

                if(SWIM_HW_Out(SWIM_CMD_ROTF, SWIM_CMD_BITLEN, SWIM_MAX_RESEND_CNT))
                {
                        return 6;
                }
                if (SWIM_HW_Out(cur_len, 8, 0))
                {
                        return 5;
                }
                if (SWIM_HW_Out((addr_tmp >> 16) & 0xFF, 8, 0))
                {
                        return 4;
                }
                if (SWIM_HW_Out((addr_tmp >> 8) & 0xFF, 8, 0))
                {
                        return 3;
                }
                if (SWIM_HW_Out((addr_tmp >> 0) & 0xFF, 8, 0))
                {
                        return 2;
                }
                for (i = 0; i < cur_len; i++)
                {
                        if (SWIM_HW_In(&data[processed_len + i], 8))
                        {
                                return 1;
                        }
                }

                cur_addr += cur_len;
                processed_len += cur_len;
        }
        return 0;
}


//测试写Flash
//镜像起始地址0x00008000
uint8_t PrgToSTM8SFlash(void)
{
        u8 i,blk;
        uint32_t DataVar;
        SWIM_RST_HIGH();
        Delay_mS(50);
        SWIM_RST_LOW();
        Delay_mS(10);
        SWIM_EnableClockInput();               
        cmdrtv=SWIM_EnterProgMode();
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 1;
        }
        Delay_mS(10);
        SWIM_Inited=0;
        SWIM_Init();
        //SWIM_Sync(16);
        SWIM_SetClockParam(8,20,2);                                                        //SWIM初始时钟为HSI/2=8MHz               
        cmdrtv=SWIM_SRST();
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 2;
        }
        Delay_mS(30);
        WriteBuff[0]=0xA0;                       
        cmdrtv=SWIM_WOTF(0x00007F80, 1, WriteBuff);          //SWIM_CSR,控制寄存器中写入0B1010,0000
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 3;
        }       
        Delay_mS(10);
        SWIM_RST_HIGH();
        Delay_mS(10);
        WriteBuff[0]=0x08;                       
        cmdrtv=SWIM_WOTF(0x00007F99,1,WriteBuff);          //DM_CSR2,Bit4 STALL =1
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 4;
        }

        WriteBuff[0]=0x56;                                                           //MASSKEY1
        cmdrtv=SWIM_WOTF(0x00005062,1,WriteBuff);           //解锁Flash区域保护
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 5;
        }
        Delay_mS(1);
        WriteBuff[0]=0xAE;                                                          //MASSKEY2
        cmdrtv=SWIM_WOTF(0x00005062,1,WriteBuff);
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 6;
        }
        Delay_mS(10);
        for (blk=0;blk<128;blk++)
        {
                WriteBuff[0]=0x01;                                                                //0000505B,Flash_CR2 ,Bit0=1,标准块编程方式
                WriteBuff[1]=0xFE;                                                                //0000505C,Flash_NCR2
                cmdrtv=SWIM_WOTF(0x0000505B,2,WriteBuff);                //每次写块数据之前都要重新配置Flash_CR2,NCR2,块写结束后被硬件自动清0
                if (cmdrtv>0)
                {
                        SWIM_Fini();
                        return 7;
                }
                //提取STM32F103C8中的镜像64字节数据--> STM8S
                for (i=0;i<16;i++)
                {
                        DataVar = (*(__IO uint32_t*)(VarStartAddr+(blk*64)+(i*4)));
                        tmpVar.ulongx=DataVar;
                        WriteBuff[i*4]=tmpVar.u8x[0];
                        WriteBuff[(i*4)+1]=tmpVar.u8x[1];
                        WriteBuff[(i*4)+2]=tmpVar.u8x[2];
                        WriteBuff[(i*4)+3]=tmpVar.u8x[3];
                }
                cmdrtv=SWIM_WOTF(0x00008000+(blk*64),64,WriteBuff);
                if (cmdrtv>0)
                {
                        SWIM_Fini();
                        return 8;
                }
                Delay_mS(10);                          //写入过程需要延时等待内部写结束
        }
        cmdrtv=SWIM_ROTF(0x00008000,64,ReadBuff);
        if (cmdrtv>0)
        {
                SWIM_Fini();
                return 9;
        }
        SWIM_Fini();
        return 0;

}





//判断Prog按钮被按下,进入脱机烧写死循环体
void OffLinePrg(void)
{
        u8 rtv1;
        Delay_mS(500);
        GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN);                        //进入脱机烧写模式,停止USB
        while(1)
        {
                  if (PROGKEY_IN==RESET)
                {
                        REDLED_On();
                        GRNLED_On();
                        rtv1=PrgToSTM8SFlash();
                        if (rtv1==0) REDLED_Off();
                        else GRNLED_Off();
                        Delay_mS(200);                       
                }
                Delay_mS(200);
        }
}


//把PC下发的镜像数据保存到芯片内部的flash区域
u8 WriteToFlash(void)
{
        u16 i,index;
        FLASH_Status tmpFLASH_Status;
        FLASH_Unlock();
        index= Receive_Buffer[2]*256+Receive_Buffer[1];                                //传入的相对偏移地址
        if (index>0x1FFF) return 1;                                                                        //仅预留8K空间
        if ((index%0x400)==0)                                                                                //STM32F103C8页大小是1024,数据是页地址的开始,要做擦除               
        {
                tmpFLASH_Status=FLASH_ErasePage(VarStartAddr+index);
                if (tmpFLASH_Status != FLASH_COMPLETE)
                {
                        return 2;
                }
        }
        for (i=0;i<32;i++)                                                                                        //每次写4字节,分32次写
        {
                tmpVar.u8x[0]=Receive_Buffer[4+i*4];
                tmpVar.u8x[1]=Receive_Buffer[5+i*4];
                tmpVar.u8x[2]=Receive_Buffer[6+i*4];
                tmpVar.u8x[3]=Receive_Buffer[7+i*4];
                VarAddr = VarStartAddr+index+i*4;                       
                tmpFLASH_Status=FLASH_ProgramWord(VarAddr , tmpVar.ulongx);
                if (tmpFLASH_Status != FLASH_COMPLETE)
                {
                        i=32;
                        return 1;
                }
        }
        FLASH_Lock();
        return 0;
}



/*******************************************************************************
* Function Name  : main.
* Description    : main routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int main(void)
{
  //FLASH_Status tmpFLASH_Status;
  u16 i;
  Set_System();
  USB_Interrupts_Config();
  Set_USBClock();
  USB_Init();
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  Delay_mS(500);                                                                          
  GPIO_WriteBit(GPIOA, GPIO_GRN_PIN, Bit_SET);
  SWIM_HIGH();
  FLASH_Lock();
  REDLED_Off();
  GRNLED_On();
  SWIM_RST_LOW();
  while (1)
  {
        SWIM_HIGH();
        if         (RecCmdFlag)                                          
        {       
                REDLED_On();               
                WriteToFlash();       
                REDLED_Off();
                RecCmdFlag=0;       
        }
        if (PROGKEY_IN==RESET)
        {
                for (i=0;i<3;i++)
                {
                        REDLED_On();
                        Delay_mS(100);
                        REDLED_Off();
                        Delay_mS(100);
                }
                REDLED_Off();
                GRNLED_On();
                OffLinePrg();
        }
  }
}





/*******************************************************************************
* Function Name  : Delay
* Description    : Inserts a delay time.
* Input          : nCount: specifies the delay time length.
* Output         : None
* Return         : None
*******************************************************************************/
void Delay(__IO uint32_t nCount)
{
  for(; nCount!= 0;nCount--);
}

void Delay_uS(u16 nUS)
{
        u8 i;
        while (nUS--)
        {
                for (i=0;i<8;i++){;;}
        }
}

void Delay_mS(u16 nMS)
{
        while(nMS--)
        {
                Delay_uS(1000);
        }
}

#ifdef  USE_FULL_ASSERT
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert_param error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert_param error line source number
* Output         : None
* Return         : 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 2010 Isaker.Co.ltd *****END OF FILE****/

使用特权

评论回复
板凳
lzmm| | 2017-5-25 22:51 | 只看该作者
有硬件的文件吗

使用特权

评论回复
地板
lzmm| | 2017-5-25 22:55 | 只看该作者
能不能应用在STM32上?

使用特权

评论回复
5
329547875| | 2020-8-27 08:39 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

121

主题

714

帖子

1

粉丝