Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable flash / ram split with minichlink #369

Merged
merged 5 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion ch32v003fun/ch32v003fun.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,19 @@ typedef struct
__IO uint32_t RES3;
} ESG_TypeDef;

typedef struct
{
union
{
__I uint32_t CHIPID;
struct
{
__I uint16_t REVID;
__I uint16_t DEVID;
};
};
} INFO_TypeDef;

#if defined(CH32V30x)
/* FSMC Bank1 Registers */
typedef struct
Expand Down Expand Up @@ -2483,7 +2496,7 @@ typedef struct

#define OB_BASE ((uint32_t)0x1FFFF800) /* Flash Option Bytes base address */
#define ESIG_BASE ((uint32_t)0x1FFFF7E0)
#define CHIP_ID *((uint32_t*)0x1FFFF704) // Mentioned in ch32v30x_dbgmcu.c, may not work on all processors.
#define INFO_BASE ((uint32_t)0x1FFFF704)

#if defined(CH32V003) || defined(CH32V10x)
#define EXTEN_BASE ((uint32_t)0x40023800)
Expand Down Expand Up @@ -2771,6 +2784,8 @@ typedef struct
#endif // defined(CH32V20x) || defined(CH32V30x)
#define OB ((OB_TypeDef *)OB_BASE)
#define ESIG ((ESG_TypeDef *)ESIG_BASE)
// Mentioned in ch32v30x_dbgmcu.c, may not work on all processors.
#define INFO ((INFO_TypeDef *)INFO_BASE)
#define EXTEN ((EXTEN_TypeDef *)EXTEN_BASE)
#define EXTEND ((EXTEND_TypeDef *)EXTEN_BASE) // Alias to EXTEN

Expand Down
12 changes: 12 additions & 0 deletions examples_v30x/check_memory_split/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
all : flash

TARGET:=check_memory_split
TARGET_MCU:=CH32V307
TARGET_MCU_PACKAGE:=CH32V307VCT6
TARGET_MCU_MEMORY_SPLIT:=3

include ../../ch32v003fun/ch32v003fun.mk

flash : cv_flash
clean : cv_clean

59 changes: 59 additions & 0 deletions examples_v30x/check_memory_split/check_memory_split.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Example testing memory option bytes on ch32v307
/*
WARNING Portions of this code are under the following copyright.
*/
/********************************** (C) COPYRIGHT *******************************
* File Name : ch32v00x_flash.c
* Author : WCH
* Version : V1.0.0
* Date : 2022/08/08
* Description : This file provides all the FLASH firmware functions.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

#include "ch32v003fun.h"
#include <stdio.h>

uint32_t count;

#ifdef TARGET_MCU_MEMORY_SPLIT
#define BUILD_MEMORY_SPLIT TARGET_MCU_MEMORY_SPLIT
#else
#define BUILD_MEMORY_SPLIT -1
#endif

int main()
{
SystemInit();

Delay_Ms( 100 );

printf("Chip ID: %08x\n", INFO->CHIPID );
printf("Device ID: %04x\n", INFO->DEVID );
printf("Revision ID: %04x\n", INFO->REVID );

printf("Option bytes in flash are: %04x\n", OB->USER );

printf("Current RAM split %d\n", (uint8_t)((FLASH->OBR >> 8) & 0x3));
printf("Flash RAM split %d\n", (uint8_t)((OB->USER >> 6) & 0x3));
printf("Build RAM split %d\n", BUILD_MEMORY_SPLIT);

// Now check the RAM capacity by sweeping a read and write back operation
// in 4k steps until we trigger a fault
printf("Testing RAM capacity:\n");

// volatile to prevent the no-op from being optimized out
volatile uint8_t *poke_addr = (void *) SRAM_BASE;

for (int i = 0; i <= 32; i++) {
uint32_t offset = 0x1000 * i;
printf("%3dk test: Poking SRAM+0x%05lx... ", i, offset);
poke_addr[offset] = poke_addr[offset];
printf("success!\n");
}

while(1);
}
6 changes: 6 additions & 0 deletions examples_v30x/check_memory_split/funconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef _FUNCONFIG_H
#define _FUNCONFIG_H


#endif

2 changes: 1 addition & 1 deletion extralibs/ch32v307gigabit.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ void ETH_IRQHandler( void )
if (int_sta & ETH_DMA_IT_RBU)
{
ETH->DMASR = ETH_DMA_IT_RBU;
if((CHIP_ID & 0xf0) == 0x10)
if((INFO->CHIPID & 0xf0) == 0x10)
{
((ETH_DMADESCTypeDef *)(((ETH_DMADESCTypeDef *)(ETH->DMACHRDR))->Buffer2NextDescAddr))->Status = ETH_DMARxDesc_OWN;
ETH->DMARPDR = 0;
Expand Down
233 changes: 233 additions & 0 deletions minichlink/minichlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,44 @@ int main( int argc, char ** argv )
else
goto unimplemented;
break;
case 'S': // Set FLASH/RAM split in option bytes
{
if( !MCF.SetSplit )
goto unimplemented;
enum RAMSplit split = FLASH_DEFAULT;

iarg+=2;
if( iarg >= argc )
{
fprintf( stderr, "FLASH/RAM split requires two values: flash size and RAM size (in kb)\n" );
goto unimplemented;
}

uint32_t flash_size = SimpleReadNumberInt( argv[iarg-1], 0);
uint32_t sram_size = SimpleReadNumberInt( argv[iarg], 0 );

if (flash_size == 192 && sram_size == 128) {
split = FLASH_192_RAM_128;
} else if (flash_size == 224 && sram_size == 96) {
split = FLASH_224_RAM_96;
} else if (flash_size == 256 && sram_size == 64) {
split = FLASH_256_RAM_64;
} else if (flash_size == 288 && sram_size == 32) {
split = FLASH_288_RAM_32;
}else if (flash_size == 128 && sram_size == 64) {
split = FLASH_128_RAM_64;
} else if (flash_size == 144 && sram_size == 48) {
split = FLASH_144_RAM_48;
} else if (flash_size == 160 && sram_size == 32) {
split = FLASH_160_RAM_32;
} else {
fprintf( stderr, "Unknown split: %dk FLASH / %dk RAM\n", flash_size, sram_size );
goto unimplemented;
}

MCF.SetSplit(dev, split);
break;
}
case 'G':
case 'T':
{
Expand Down Expand Up @@ -692,6 +730,7 @@ int main( int argc, char ** argv )
fprintf( stderr, " -G Terminal + GDB (must be last arg)\n" );
fprintf( stderr, " -P Enable Read Protection\n" );
fprintf( stderr, " -p Disable Read Protection\n" );
fprintf( stderr, " -S set FLASH/SRAM split [FLASH kbytes] [SRAM kbytes]\n" );
fprintf( stderr, " -w [binary image to write] [address, decimal or 0x, try0x08000000]\n" );
fprintf( stderr, " -r [output binary image] [memory address, decimal or 0x, try 0x08000000] [size, decimal or 0x, try 16384]\n" );
fprintf( stderr, " Note: for memory addresses, you can use 'flash' 'launcher' 'bootloader' 'option' 'ram' and say \"ram+0x10\" for instance\n" );
Expand Down Expand Up @@ -1566,6 +1605,198 @@ int DefaultErase( void * dev, uint32_t address, uint32_t length, int type )
return -93;
}

static int DefaultSetSplit(void * dev, enum RAMSplit split) {

uint8_t split_code = 0;
uint16_t option_bytes = 0;
uint32_t flash_ctlr = 0;
struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);


// If the progammer already read the chip_id, use it
// Otherwise read it off the chip
uint32_t chip_id = iss->target_chip_id;
if (!chip_id) {
if( MCF.ReadWord( dev, (intptr_t)&INFO->CHIPID, &chip_id ) ) goto flashoperr;
}

uint32_t chip = chip_id & 0xFFFFFF0F;

/* List of ChipIDs
* Values taken from: ch32v307/EVT/EXAM/SRC/Peripheral/src/ch32v30x_dbgmcu.c:108
* CH32V303CBT6: 0x303305x4
* CH32V303RBT6: 0x303205x4
* CH32V303RCT6: 0x303105x4
* CH32V303VCT6: 0x303005x4
* CH32V305FBP6: 0x305205x8
* CH32V305RBT6: 0x305005x8
* CH32V305GBU6: 0x305B05x8
* CH32V307WCU6: 0x307305x8
* CH32V307FBP6: 0x307205x8
* CH32V307RCT6: 0x307105x8
* CH32V307VCT6: 0x307005x8
* CH32V317VCT6: 0x3170B5X8
* CH32V317WCU6: 0x3173B5X8
* CH32V317TCU6: 0x3175B5X8
*/

switch (split)
{
case FLASH_192_RAM_128:
if (chip == 0x30700508
|| chip == 0x30710508
|| chip == 0x30730508
|| chip == 0x30300504
|| chip == 0x30310504
|| chip == 0x30720508
|| chip == 0x30740508) {
split_code = 0;
} else {
fprintf( stderr, "Error, 192k/128k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_224_RAM_96:
if (chip == 0x30700508
|| chip == 0x30710508
|| chip == 0x30730508
|| chip == 0x30300504
|| chip == 0x30310504
|| chip == 0x30720508
|| chip == 0x30740508) {
split_code = 1;
} else {
fprintf( stderr, "Error, 224k/96k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_256_RAM_64:
if (chip == 0x30700508
|| chip == 0x30710508
|| chip == 0x30730508
|| chip == 0x30300504
|| chip == 0x30310504) {
split_code = 2;
} else {
fprintf( stderr, "Error, 256k/64k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_288_RAM_32:
if (chip == 0x30700508
|| chip == 0x30710508
|| chip == 0x30730508
|| chip == 0x30300504
|| chip == 0x30310504) {
split_code = 3;
} else {
fprintf( stderr, "Error, 288k/32k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_128_RAM_64:
if (chip == 0x2034050c
|| chip == 0x2080050c
|| chip == 0x2081050c
|| chip == 0x2082050c
|| chip == 0x2083050c) {
split_code = 0;
} else {
fprintf( stderr, "Error, 128k/64k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_144_RAM_48:
if (chip == 0x2034050c
|| chip == 0x2080050c
|| chip == 0x2081050c
|| chip == 0x2082050c
|| chip == 0x2083050c) {
split_code = 1;
} else {
fprintf( stderr, "Error, 144k/48k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

case FLASH_160_RAM_32:
if (chip == 0x2034050c
|| chip == 0x2080050c
|| chip == 0x2081050c
|| chip == 0x2082050c
|| chip == 0x2083050c) {
split_code = 2;
} else {
fprintf( stderr, "Error, 160k/32k split not supported for chip 0x%08x\n", chip);
exit( -110 );
}
break;

default:
fprintf( stderr, "Error: chip 0x%08x does not support a configurable RAM split\n", chip);
return -110;

}

if( !MCF.WriteHalfWord || !MCF.ReadHalfWord)
{
fprintf( stderr, "Error: for setting ram split option bytes, half-word read and write is required\n" );
return -5;
}

if( MCF.ReadHalfWord( dev, (intptr_t)&OB->USER, &option_bytes ) ) goto flashoperr;
printf("initial option_bytes = %04x\n", option_bytes);


// Option byte b is stored as 16 bits (~b << 8)|b
// Mask off upper copy and clear split bits
option_bytes &= 0x003F;
// Set split code at [7:6]
option_bytes |= split_code << 6;
// Add inverted copy back as high byte
option_bytes |= (~option_bytes) << 8;

InternalUnlockFlash(dev, iss);

if( MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &flash_ctlr ) ) goto flashoperr;
flash_ctlr |= CR_OPTER_Set;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, flash_ctlr ) ) goto flashoperr;
flash_ctlr |= CR_STRT_Set;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, flash_ctlr ) ) goto flashoperr;
if( MCF.WaitForFlash(dev) ) goto flashoperr;

if( MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &flash_ctlr ) ) goto flashoperr;
flash_ctlr &= CR_OPTER_Reset;
flash_ctlr |= CR_OPTPG_Set;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, flash_ctlr ) ) goto flashoperr;
if( MCF.WriteWord( dev, (intptr_t)&OB->RDPR, RDP_Key ) ) goto flashoperr;
if( MCF.WaitForFlash(dev) ) goto flashoperr;

if( MCF.WriteWord( dev, (intptr_t)&FLASH->OBKEYR, FLASH_KEY1 ) ) goto flashoperr;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->OBKEYR, FLASH_KEY2 ) ) goto flashoperr;
if( MCF.WaitForFlash(dev) ) goto flashoperr;

if( MCF.ReadWord( dev, (intptr_t)&FLASH->CTLR, &flash_ctlr ) ) goto flashoperr;
flash_ctlr |= CR_OPTPG_Set;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, flash_ctlr ) ) goto flashoperr;
if( MCF.WriteHalfWord( dev, (intptr_t)&OB->USER, option_bytes ) ) goto flashoperr;
if( MCF.WaitForFlash(dev) ) goto flashoperr;

flash_ctlr &= CR_OPTPG_Reset;
if( MCF.WriteWord( dev, (intptr_t)&FLASH->CTLR, flash_ctlr ) ) goto flashoperr;
if( MCF.WaitForFlash(dev) ) goto flashoperr;

return 0;
flashoperr:
fprintf( stderr, "Error: Flash operation error\n" );
return -93;
}

void PostSetupConfigureInterface( void * dev )
{
struct InternalState * iss = (struct InternalState*)(((struct ProgrammerStructBase*)dev)->internal);
Expand Down Expand Up @@ -2023,6 +2254,8 @@ int SetupAutomaticHighLevelFunctions( void * dev )
MCF.Erase = DefaultErase;
if( !MCF.HaltMode )
MCF.HaltMode = DefaultHaltMode;
if( !MCF.SetSplit )
MCF.SetSplit = DefaultSetSplit;
if( !MCF.PollTerminal )
MCF.PollTerminal = DefaultPollTerminal;
if( !MCF.WaitForFlash )
Expand Down
Loading
Loading