yes
This commit is contained in:
@@ -1,121 +1,111 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2016 Rebane, rebane@alkohol.ee
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||
* Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include "rtl8710.h"
|
||||
#include "rtl8710_flasher.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "spi_flash.h"
|
||||
#include <string.h>
|
||||
|
||||
#define MEM_START (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x00))
|
||||
#define MEM_COMMAND (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x04))
|
||||
#define MEM_STATUS (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x08))
|
||||
#define MEM_PARAM (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x0C))
|
||||
#define MEM_OFFSET (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x10))
|
||||
#define MEM_LEN (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x14))
|
||||
#define MEM_DATA ((volatile uint8_t *)(BUFFER_ADDRESS + 0x20))
|
||||
#define printf DiagPrintf
|
||||
|
||||
#define COMMAND_READ_ID 0
|
||||
#define COMMAND_MASS_ERASE 1
|
||||
#define COMMAND_SECTOR_ERASE 2
|
||||
#define COMMAND_READ 3
|
||||
#define COMMAND_WRITE 4
|
||||
#define COMMAND_VERIFY 5
|
||||
|
||||
int __attribute__((section(".vectors"))) main(){
|
||||
uint32_t p, i, l;
|
||||
uint8_t read_buffer[16];
|
||||
|
||||
__asm__("cpsid f");
|
||||
|
||||
PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_GPIO_EN | PERI_ON_CLK_CTRL_SLPCK_GPIO_EN; // enable gpio peripheral clock
|
||||
PERI_ON->SOC_PERI_FUNC1_EN |= PERI_ON_SOC_PERI_FUNC1_EN_GPIO; // enable gpio peripheral
|
||||
|
||||
PERI_ON->GPIO_SHTDN_CTRL = 0xFF;
|
||||
PERI_ON->GPIO_DRIVING_CTRL = 0xFF;
|
||||
|
||||
spi_flash_init();
|
||||
|
||||
// read jedec info
|
||||
spi_flash_wait_busy();
|
||||
MEM_PARAM = spi_flash_jedec_id();
|
||||
spi_flash_wait_busy();
|
||||
|
||||
while(1){
|
||||
MEM_START = 0x00000000;
|
||||
while(MEM_START == 0x00000000);
|
||||
if(MEM_COMMAND == COMMAND_READ_ID){
|
||||
MEM_PARAM = 0x00000000;
|
||||
spi_flash_wait_busy();
|
||||
MEM_PARAM = spi_flash_jedec_id();
|
||||
spi_flash_wait_busy();
|
||||
}else if(MEM_COMMAND == COMMAND_MASS_ERASE){
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x06);
|
||||
spi_flash_wait_wel();
|
||||
spi_flash_cmd(0xC7);
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x04);
|
||||
spi_flash_wait_busy();
|
||||
}else if(MEM_COMMAND == COMMAND_SECTOR_ERASE){
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x06);
|
||||
spi_flash_wait_wel();
|
||||
spi_flash_sector_erase(MEM_OFFSET);
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x04);
|
||||
spi_flash_wait_busy();
|
||||
}else if(MEM_COMMAND == COMMAND_READ){
|
||||
spi_flash_wait_busy();
|
||||
p = MEM_OFFSET;
|
||||
for(i = 0; i < MEM_LEN; i += 16, p += 16){
|
||||
spi_flash_read(p, (void *)&MEM_DATA[i], 16);
|
||||
}
|
||||
spi_flash_wait_busy();
|
||||
}else if(MEM_COMMAND == COMMAND_WRITE){
|
||||
for(p = 0; p < MEM_LEN; p += 256){
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x06);
|
||||
spi_flash_wait_wel();
|
||||
spi_flash_write((MEM_OFFSET + p), (void *)&MEM_DATA[p], 256);
|
||||
spi_flash_wait_busy();
|
||||
spi_flash_cmd(0x04);
|
||||
spi_flash_wait_busy();
|
||||
}
|
||||
}else if(MEM_COMMAND == COMMAND_VERIFY){
|
||||
spi_flash_wait_busy();
|
||||
for(p = 0; p < MEM_LEN; p += 16){
|
||||
spi_flash_read((MEM_OFFSET + p), read_buffer, 16);
|
||||
l = MEM_LEN - p;
|
||||
if(l > 16)l = 16;
|
||||
for(i = 0; i < l; i++){
|
||||
if(read_buffer[i] != MEM_DATA[p + i]){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i < l){
|
||||
MEM_STATUS = 0x00000001;
|
||||
MEM_PARAM = p;
|
||||
break;
|
||||
}
|
||||
spi_flash_wait_busy();
|
||||
}
|
||||
}else{
|
||||
MEM_STATUS = 0x00000001;
|
||||
}
|
||||
}
|
||||
static void print_flash_info(const uint8_t *flash_id) {
|
||||
printf("[FLASH] Device ID: %02X %02X %02X\n", flash_id[0], flash_id[1],
|
||||
flash_id[2]);
|
||||
printf("[FLASH] Vendor: 0x%08X\n", flash_init_para.vendor_id);
|
||||
printf("[FLASH] Config: Mode=%d, Clock=%d, ReadCmd=0x%02X\n",
|
||||
flash_init_para.current_mode, flash_init_para.clock_div,
|
||||
flash_init_para.current_read_cmd);
|
||||
printf("[FLASH] Timing: SampleDelay=%d, DummyCycles=[%d,%d,%d]\n",
|
||||
flash_init_para.read_sample_delay,
|
||||
flash_init_para.read_dummy_cycles[0],
|
||||
flash_init_para.read_dummy_cycles[1],
|
||||
flash_init_para.read_dummy_cycles[2]);
|
||||
}
|
||||
|
||||
int __attribute__((section(".vectors"))) main(void) {
|
||||
__asm__ volatile("cpsid if");
|
||||
|
||||
uint8_t flash_id[4] = {0};
|
||||
|
||||
// sometimes we boot up and the ROM already inits flash?
|
||||
if (PERI_ON_SOC_FUNC_EN & FLASH_PERIPH_BIT) {
|
||||
printf("[FLASHER] Flash peripheral already enabled...?\n");
|
||||
}
|
||||
|
||||
RCC_PeriphClockCmd(FLASH_PERIPH_BIT, FLASH_CLOCK_BIT, 0);
|
||||
FLASH_ClockDiv(0);
|
||||
RCC_PeriphClockCmd(FLASH_PERIPH_BIT, FLASH_CLOCK_BIT, 1);
|
||||
|
||||
PINMUX_Ctrl(10, 0, 1);
|
||||
FLASH_StructInit_GD(&flash_init_para);
|
||||
FLASH_Init(2);
|
||||
|
||||
FLASH_RxCmd(flash_init_para.cmd_read_id, 3, flash_id);
|
||||
print_flash_info(flash_id);
|
||||
|
||||
/* clear block protection */
|
||||
FLASH_SetStatusBits(0x1c, 0);
|
||||
printf("[FLASH] Block protection cleared\n");
|
||||
|
||||
while (1) {
|
||||
FLASH_CONTROL->start = 0;
|
||||
while (!FLASH_CONTROL->start) __asm__("nop");
|
||||
|
||||
switch (FLASH_CONTROL->cmd) {
|
||||
case CMD_READ_ID:
|
||||
FLASH_RxCmd(flash_init_para.cmd_read_id, 4, flash_id);
|
||||
FLASH_CONTROL->param = *(uint32_t *)flash_id;
|
||||
break;
|
||||
|
||||
case CMD_MASS_ERASE:
|
||||
FLASH_Erase(0, 0);
|
||||
printf("[FLASHER] Full chip erase completed\n");
|
||||
break;
|
||||
|
||||
case CMD_SECTOR_ERASE:
|
||||
FLASH_Erase(2, FLASH_CONTROL->offset);
|
||||
break;
|
||||
|
||||
case CMD_READ:
|
||||
for (uint32_t i = 0; i < FLASH_CONTROL->len; i += 4) {
|
||||
volatile uint32_t *flash_addr =
|
||||
(volatile uint32_t *)(SPI_FLASH_BASE + FLASH_CONTROL->offset + i);
|
||||
uint32_t *dest = (uint32_t *)&FLASH_CONTROL->data[i];
|
||||
*dest = *flash_addr;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_WRITE:
|
||||
printf("[FLASHER] Starting write of %d bytes at offset 0x%08X\n",
|
||||
FLASH_CONTROL->len, FLASH_CONTROL->offset);
|
||||
|
||||
for (uint32_t offset = 0; offset < FLASH_CONTROL->len; offset += 4) {
|
||||
uint32_t write_addr = FLASH_CONTROL->offset + offset;
|
||||
FLASH_TxData12B(write_addr, 4,
|
||||
(uint8_t *)&FLASH_CONTROL->data[offset]);
|
||||
}
|
||||
|
||||
printf("[FLASHER] Write completed successfully\n");
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
for (uint32_t i = 0; i < FLASH_CONTROL->len; i += VERIFY_CHUNK_SIZE) {
|
||||
size_t bytes_to_compare = MIN(4, FLASH_CONTROL->len - i);
|
||||
const void *flash_addr =
|
||||
(const void *)(SPI_FLASH_BASE + FLASH_CONTROL->offset + i);
|
||||
|
||||
if (memcmp(flash_addr, (const void *)&FLASH_CONTROL->data[i],
|
||||
bytes_to_compare) != 0) {
|
||||
FLASH_CONTROL->status = 1;
|
||||
FLASH_CONTROL->param = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FLASH_CONTROL->status = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user