Browse Source

Add files via upload

master
jmichault 5 years ago
committed by GitHub
parent
commit
d8ca5ff03a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1428 additions and 0 deletions
  1. +767
    -0
      CCDebugger.c
  2. +121
    -0
      CCDebugger.h
  3. +23
    -0
      Makefile
  4. BIN
      cc_chipid
  5. +37
    -0
      cc_chipid.c
  6. BIN
      cc_erase
  7. +41
    -0
      cc_erase.c
  8. BIN
      cc_read
  9. +107
    -0
      cc_read.c
  10. BIN
      cc_write
  11. +332
    -0
      cc_write.c

+ 767
- 0
CCDebugger.c View File

@@ -0,0 +1,767 @@
/***********************************************************************
* Copyright (c) 2014-2016 Ioannis Charalampidis
* Copyright (c) 2015 Simon Schulz - github.com/fishpepper
Copyright © 2019 Jean Michault.
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 3 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, see <https://www.gnu.org/licenses/>.
*************************************************************************/

#include <wiringPi.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>

#include "CCDebugger.h"

/**
* Switch reset pin
*/
void cc_setDDDirection( uint8_t direction );

/**
* Software-overridable instruction table that can be used
* for supporting other CCDebug-Compatible chips purely by software
*/
uint8_t instr[16];

/**
* Local properties
*/
int pinRST=24;
int pinDC=28;
int pinDD=29;
uint8_t errorFlag=0;
uint8_t ddIsOutput=false;
uint8_t inDebugMode=false;
uint8_t cc_active=false;


/**
* Instruction table indices
*/
#define INSTR_VERSION 0
#define I_HALT 1
#define I_RESUME 2
#define I_RD_CONFIG 3
#define I_WR_CONFIG 4
#define I_DEBUG_INSTR_1 5
#define I_DEBUG_INSTR_2 6
#define I_DEBUG_INSTR_3 7
#define I_GET_CHIP_ID 8
#define I_GET_PC 9
#define I_READ_STATUS 10
#define I_STEP_INSTR 11
#define I_CHIP_ERASE 12

#define I_SET_HW_BRKPNT 13
#define I_GET_BM 14
#define I_BURST_WRITE 15

int cc_init( int pRST, int pDC, int pDD )
{
if(wiringPiSetup() == -1){
printf("no wiring pi detected\n");
return 0;
}

pinRST=pRST;
pinDC=pDC;
pinDD=pDD;

// Prepare CC Pins
pinMode(pinDC, OUTPUT);
pinMode(pinDD, OUTPUT);
pinMode(pinRST, OUTPUT);
digitalWrite(pinDC, LOW);
digitalWrite(pinDD, LOW);
digitalWrite(pinRST, LOW);

// Prepare default direction
cc_setDDDirection(INPUT);

// Default CCDebug instruction set for CC254x
instr[INSTR_VERSION] = 1;
instr[I_HALT] = 0x40;
instr[I_RESUME] = 0x48;
instr[I_RD_CONFIG] = 0x20;
instr[I_WR_CONFIG] = 0x18;
instr[I_DEBUG_INSTR_1] = 0x51;
instr[I_DEBUG_INSTR_2] = 0x52;
instr[I_DEBUG_INSTR_3] = 0x53;
instr[I_GET_CHIP_ID] = 0x68;
instr[I_GET_PC] = 0x28;
instr[I_READ_STATUS] = 0x30;
instr[I_STEP_INSTR] = 0x58;
instr[I_CHIP_ERASE] = 0x10;

// We are active by default
cc_active = true;

};

/**
* Activate/Deactivate debugger
*/
void cc_setActive( uint8_t on )
{

// Reset error flag
errorFlag = CC_ERROR_NONE;

// Continue only if active
if (on == cc_active) return;
cc_active = on;

if (on) {

// Prepare CC Pins
pinMode(pinDC, OUTPUT);
pinMode(pinDD, OUTPUT);
pinMode(pinRST, OUTPUT);
digitalWrite(pinDC, LOW);
digitalWrite(pinDD, LOW);
digitalWrite(pinRST, LOW);

// Default direction is INPUT
cc_setDDDirection(INPUT);

} else {

// Before deactivating, exit debug mode
if (inDebugMode)
cc_exit();

// Put everything in inactive mode
pinMode(pinDC, INPUT);
pinMode(pinDD, INPUT);
pinMode(pinRST, INPUT);
digitalWrite(pinDC, LOW);
digitalWrite(pinDD, LOW);
digitalWrite(pinRST, LOW);

}
}

/**
* Return the error flag
*/
uint8_t cc_error()
{
return errorFlag;
}

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//// LOW LEVEL FUNCTIONS ////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

/**
* Delay a particular number of cycles
*/
struct timespec tp={0,0};
void cc_delay( unsigned char d )
{
volatile unsigned char i = 50*d;
while( i-- );
//tp.tv_nsec=40*d;
//nanosleep(&tp,NULL);

}

/**
* Enter debug mode
*/
uint8_t cc_enter()
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
// =============

// Reset error flag
errorFlag = CC_ERROR_NONE;

// Enter debug mode
digitalWrite(pinRST, LOW);
cc_delay(200);
digitalWrite(pinDC, HIGH);
cc_delay(3);
digitalWrite(pinDC, LOW);
cc_delay(3);
digitalWrite(pinDC, HIGH);
cc_delay(3);
digitalWrite(pinDC, LOW);
cc_delay(4);
digitalWrite(pinRST, HIGH);
cc_delay(200);

// We are now in debug mode
inDebugMode = 1;

// =============

// Success
return 0;

};

/**
* Write a uint8_t to the debugger
*/
uint8_t cc_write( uint8_t data )
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
};
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}
// =============

uint8_t cnt;

// Make sure DD is on output
cc_setDDDirection(OUTPUT);

// Sent uint8_ts
for (cnt = 8; cnt; cnt--) {

// First put data bit on bus
if (data & 0x80)
digitalWrite(pinDD, HIGH);
else
digitalWrite(pinDD, LOW);

// Place clock on high (other end reads data)
digitalWrite(pinDC, HIGH);

// Shift & Delay
data <<= 1;
cc_delay(2);

// Place clock down
digitalWrite(pinDC, LOW);
cc_delay(2);

}

// =============
return 0;
}

/**
* Wait until input is ready for reading
*/
uint8_t cc_switchRead(uint8_t maxWaitCycles)
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}
// =============

uint8_t cnt;
uint8_t didWait = 0;

// Switch to input
cc_setDDDirection(INPUT);

// Wait at least 83 ns before checking state t(dir_change)
cc_delay(2);

// Wait for DD to go LOW (Chip is READY)
while (digitalRead(pinDD) == HIGH) {

// Do 8 clock cycles
for (cnt = 8; cnt; cnt--) {
digitalWrite(pinDC, HIGH);
cc_delay(2);
digitalWrite(pinDC, LOW);
cc_delay(2);
}

// Let next function know that we did wait
didWait = 1;

// Check if we ran out if wait cycles
if (!--maxWaitCycles) {

// If we are waiting for too long, we have lost the chip,
// so also assume we are out of debugging mode
errorFlag = CC_ERROR_NOT_WIRED;
inDebugMode = 0;


return 0;
}
}

// Wait t(sample_wait)
if (didWait) cc_delay(2);

// =============
return 0;
}

/**
* Switch to output
*/
uint8_t cc_switchWrite()
{
cc_setDDDirection(OUTPUT);
return 0;
}

/**
* Read an input uint8_t
*/
uint8_t cc_read()
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
// =============

uint8_t cnt;
uint8_t data = 0;

// Switch to input
cc_setDDDirection(INPUT);

// Send 8 clock pulses if we are HIGH
for (cnt = 8; cnt; cnt--) {
digitalWrite(pinDC, HIGH);
cc_delay(2);

// Shift and read
data <<= 1;
if (digitalRead(pinDD) == HIGH)
data |= 0x01;

digitalWrite(pinDC, LOW);
cc_delay(2);
}

// =============
return data;
}

/**
* Switch reset pin
*/
void cc_setDDDirection( uint8_t direction )
{

// Switch direction if changed
if (direction == ddIsOutput) return;
ddIsOutput = direction;

// Handle new direction
if (ddIsOutput) {
digitalWrite(pinDD, LOW); // Disable pull-up
pinMode(pinDD, OUTPUT); // Enable output
digitalWrite(pinDD, LOW); // Switch to low
} else {
digitalWrite(pinDD, LOW); // Disable pull-up
pinMode(pinDD, INPUT); // Disable output
digitalWrite(pinDD, LOW); // Don't use output pull-up
}

}

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//// HIGH LEVEL FUNCTIONS ////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////


/**
* Exit from debug mode
*/
uint8_t cc_exit()
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_RESUME] ); // RESUME
cc_switchRead(250);
bAns = cc_read(); // debug status
cc_switchWrite();

inDebugMode = 0;

return 0;
}
/**
* Get debug configuration
*/
uint8_t cc_getConfig() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_RD_CONFIG] ); // RD_CONFIG
cc_switchRead(250);
bAns = cc_read(); // Config
cc_switchWrite();

return bAns;
}

/**
* Set debug configuration
*/
uint8_t cc_setConfig( uint8_t config ) {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_WR_CONFIG] ); // WR_CONFIG
cc_write( config );
cc_switchRead(250);
bAns = cc_read(); // Config
cc_switchWrite();

return bAns;
}

/**
* Invoke a debug instruction with 1 opcode
*/
uint8_t cc_exec( uint8_t oc0 )
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_DEBUG_INSTR_1] ); // DEBUG_INSTR + 1b
cc_write( oc0 );
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* Invoke a debug instruction with 2 opcodes
*/
uint8_t cc_exec2( uint8_t oc0, uint8_t oc1 )
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_DEBUG_INSTR_2] ); // DEBUG_INSTR + 2b
cc_write( oc0 );
cc_write( oc1 );
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* Invoke a debug instruction with 3 opcodes
*/
uint8_t cc_exec3( uint8_t oc0, uint8_t oc1, uint8_t oc2 )
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_DEBUG_INSTR_3] ); // DEBUG_INSTR + 3b
cc_write( oc0 );
cc_write( oc1 );
cc_write( oc2 );
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* Invoke a debug instruction with 1 opcode + 16-bit immediate
*/
uint8_t cc_execi( uint8_t oc0, unsigned short c0 )
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_DEBUG_INSTR_3] ); // DEBUG_INSTR + 3b
cc_write( oc0 );
cc_write( (c0 >> 8) & 0xFF );
cc_write( c0 & 0xFF );
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* Return chip ID
*/
unsigned short cc_getChipID() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

unsigned short bAns;
uint8_t bRes;

cc_write( instr[I_GET_CHIP_ID] ); // GET_CHIP_ID
cc_switchRead(250);

bRes = cc_read(); // High order
bAns = bRes << 8;
bRes = cc_read(); // Low order
bAns |= bRes;
cc_switchWrite();

return bAns;
}

/**
* Return PC
*/
unsigned short cc_getPC() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

unsigned short bAns;
uint8_t bRes;

cc_write( instr[I_GET_PC] ); // GET_PC
cc_switchRead(250);
bRes = cc_read(); // High order
bAns = bRes << 8;
bRes = cc_read(); // Low order
bAns |= bRes;
cc_switchWrite();

return bAns;
}

/**
* Return debug status
*/
uint8_t cc_getStatus() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_READ_STATUS] ); // READ_STATUS
cc_switchRead(250);
bAns = cc_read(); // debug status
cc_switchWrite();

return bAns;
}

/**
* Step instruction
*/
uint8_t cc_step() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_STEP_INSTR] ); // STEP_INSTR
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* resume instruction
*/
uint8_t cc_resume() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_RESUME] ); //RESUME
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* halt instruction
*/
uint8_t cc_halt() {
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
}
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_HALT] ); //HALT
cc_switchRead(250);
bAns = cc_read(); // Accumulator
cc_switchWrite();

return bAns;
}

/**
* Mass-erase all chip configuration & Lock Bits
*/
uint8_t cc_chipErase()
{
if (!cc_active) {
errorFlag = CC_ERROR_NOT_ACTIVE;
return 0;
};
if (!inDebugMode) {
errorFlag = CC_ERROR_NOT_DEBUGGING;
return 0;
}

uint8_t bAns;

cc_write( instr[I_CHIP_ERASE] ); // CHIP_ERASE
cc_switchRead(250);
bAns = cc_read(); // Debug status
cc_switchWrite();

return bAns;
}

/**
* Update the debug instruction table
*/
uint8_t cc_updateInstructionTable( uint8_t newTable[16] )
{
// Copy table entries
for (uint8_t i=0; i<16; i++)
instr[i] = newTable[i];
// Return the new version
return instr[INSTR_VERSION];
}

/**
* Get the instruction table version
*/
uint8_t cc_getInstructionTableVersion()
{
// Return version of instruction table
return instr[INSTR_VERSION];
}

+ 121
- 0
CCDebugger.h View File

@@ -0,0 +1,121 @@

#ifndef CCDEBUGGER_H
#define CCDEBUGGER_H

#define CC_ERROR_NONE 0
#define CC_ERROR_NOT_ACTIVE 1
#define CC_ERROR_NOT_DEBUGGING 2
#define CC_ERROR_NOT_WIRED 3


int cc_init( int pinRST, int pinDC, int pinDD );
void cc_delay( unsigned char d );

uint8_t cc_error();

////////////////////////////
// High-Level interaction
////////////////////////////
void cc_setActive( uint8_t on );

/**
* Enter debug mode
*/
uint8_t cc_enter();

/**
* Exit from debug mode
*/
uint8_t cc_exit();

/**
* Execute a CPU instructuion
*/
uint8_t cc_exec( uint8_t oc0 );
uint8_t cc_execi( uint8_t oc0, unsigned short c0 );
uint8_t cc_exec2( uint8_t oc0, uint8_t oc1 );
uint8_t cc_exec3( uint8_t oc0, uint8_t oc1, uint8_t oc2 );

/**
* Return chip ID
*/
unsigned short cc_getChipID();

/**
* Return PC
*/
unsigned short cc_getPC();

/**
* Return debug status
*/
uint8_t cc_getStatus();

/**
* resume program exec
*/
uint8_t cc_resume();

/**
* halt program exec
*/
uint8_t cc_halt();

/**
* Step a single instruction
*/
uint8_t cc_step();

/**
* Get debug configuration
*/
uint8_t cc_getConfig();

/**
* Set debug configuration
*/
uint8_t cc_setConfig( uint8_t config );

/**
* Massive erasure on the chip
*/
uint8_t cc_chipErase();

////////////////////////////
// Low-level interaction
////////////////////////////

/**
* Write to the debugger
*/
uint8_t cc_write( uint8_t data );

/**
* Wait until we are ready to read & Switch to read mode
*/
uint8_t cc_switchRead( uint8_t maxWaitCycles );

/**
* Switch to write mode
*/
uint8_t cc_switchWrite();

/**
* Read from the debugger
*/
uint8_t cc_read();

/**
* Update the debug instruction table
*/
uint8_t cc_updateInstructionTable( uint8_t newTable[16] );

/**
* Get the instruction table version
*/
uint8_t cc_getInstructionTableVersion();



#endif


+ 23
- 0
Makefile View File

@@ -0,0 +1,23 @@
LDLIBS=-lwiringPi
CFLAGS=-g
LDFLAGS=-g

all: cc_chipid cc_read cc_write cc_erase

cc_erase : cc_erase.o CCDebugger.o
gcc $(LDFLAGS) -o $@ $^ $(LDLIBS)

cc_write : cc_write.o CCDebugger.o
gcc $(LDFLAGS) -o $@ $^ $(LDLIBS)

cc_read : cc_read.o CCDebugger.o
gcc $(LDFLAGS) -o $@ $^ $(LDLIBS)

cc_chipid : cc_chipid.o CCDebugger.o
gcc $(LDFLAGS) -o $@ $^ $(LDLIBS)

cc_chipid.o : cc_chipid.c CCDebugger.h
gcc $(CFLAGS) -c $*.c

CCDebugger.o : CCDebugger.c CCDebugger.h
gcc $(CFLAGS) -c $*.c

BIN
cc_chipid View File


+ 37
- 0
cc_chipid.c View File

@@ -0,0 +1,37 @@
/***********************************************************************
Copyright © 2019 Jean Michault.
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 3 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, see <https://www.gnu.org/licenses/>.
*************************************************************************/

#include <wiringPi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>

#include "CCDebugger.h"

int main()
{
// initialize GPIO and debugger
cc_init(24,27,28);
// enter debug mode
cc_enter();
// get ChipID :
uint16_t res;
res = cc_getChipID();
printf(" ID = %04x.\n",res);
cc_setActive(false);
}

BIN
cc_erase View File


+ 41
- 0
cc_erase.c View File

@@ -0,0 +1,41 @@
/***********************************************************************
Copyright © 2019 Jean Michault.
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 3 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, see <https://www.gnu.org/licenses/>.
*************************************************************************/

#include <wiringPi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>

#include "CCDebugger.h"

int main()
{
// initialize GPIO and debugger
cc_init(24,27,28);
// enter debug mode
cc_enter();
// get ChipID :
uint16_t res;
res = cc_getChipID();
printf(" ID = %04x.\n",res);
// erase flash
res = cc_chipErase();
printf(" erase result = %04x.\n",res);
cc_setActive(false);

}

BIN
cc_read View File


+ 107
- 0
cc_read.c View File

@@ -0,0 +1,107 @@
/***********************************************************************
Copyright © 2019 Jean Michault.
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 3 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, see <https://www.gnu.org/licenses/>.
*************************************************************************/

#include <wiringPi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>

#include "CCDebugger.h"

void writeHexLine(FILE * fic,uint8_t *buf, int len,int offset)
{
int i=0;
for(i=0 ; i<len ; i++)
if(buf[i] != 0xff) break;
if(i==len) return;
int sum=len+(offset&0xff)+((offset>>8)&0xff);
fprintf(fic,":%02X%04X00",len,offset);
for(int i=0 ; i<len;i++)
{
fprintf(fic,"%02X",buf[i]);
sum += buf[i];
}
fprintf(fic,"%02X\n",(-sum)&0xff);
}

uint8_t buf1[1024];
uint8_t buf2[1024];

void read1k(int bank,uint16_t offset,uint8_t * buf)
{
// get FMAP
uint8_t res = cc_exec2(0xE5, 0xC7);
// select bank
res = (res & 0xF8) | (bank & 0x07);
res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data
// Setup DPTR
cc_execi( 0x90, 0x8000+offset ); // MOV DPTR,#data16
for(int i=0 ; i<1024 ;i++)
{
res = cc_exec ( 0xE0 ); // MOVX A,@DPTR
buf[i] = res;
res = cc_exec ( 0xA3 ); // INC DPTR
}
}

int main(int argc,char **argv)
{
if( argc <2 ) { fprintf(stderr,"usage : %s outfile\n",argv[0]); exit(1); }
FILE * ficout = fopen(argv[1],"w");
if(!ficout) { fprintf(stderr," Can't open file %s.\n",argv[1]); exit(1); }
// initialize GPIO ports
cc_init(24,27,28);
// enter debug mode
cc_enter();
// get ChipID :
uint16_t ID;
ID = cc_getChipID();
printf(" ID = %04x.\n",ID);

uint16_t offset=0;
uint8_t bank=0;
int progress=1;
for( bank=0 ; bank<8 ; bank++)
{
printf(".");fflush(stdout);
if(! (bank&1))
{
uint8_t sum=2+4+(bank/2);
fprintf(ficout,":02000004%04X%02X\n",bank/2,(-sum)&255 );
}
offset=0;
int len=0;
uint8_t buf[17];
for ( uint16_t i=0 ; i<32 ; i++ )
{
do
{
read1k(bank,i*1024, buf1);
read1k(bank,i*1024, buf2);
} while(memcmp(buf1,buf2,1024));
for(uint16_t j=0 ; j<64 ; j++)
writeHexLine(ficout,buf1+j*16, 16,(bank&1)*32*1024+ i*1024+j*16);
printf("\r reading %dk/256k",progress++);fflush(stdout);
}
}
fprintf(ficout,":00000001FF\n");
// exit from debug
cc_setActive(false);
fclose(ficout);

}

BIN
cc_write View File


+ 332
- 0
cc_write.c View File

@@ -0,0 +1,332 @@
/***********************************************************************
Copyright © 2019 Jean Michault.
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 3 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, see <https://www.gnu.org/licenses/>.
*************************************************************************/

#include <wiringPi.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

#include "CCDebugger.h"

uint8_t buffer[601];
uint8_t data[260];
uint8_t buf1[1024];
uint8_t buf2[1024];

struct page
{
uint32_t minoffset,maxoffset;
uint8_t datas[2048];
} Pages[128];



void readXDATA(uint16_t offset,uint8_t *bytes, int len)
{
cc_execi(0x90, offset ); //MOV DPTR,#data16
for ( int i=0 ; i<len;i++)
{
bytes[i] = cc_exec(0xE0); //MOVX A,@DPTR
cc_exec(0xA3); // INC DPTR
}
}

void writeXDATA(uint16_t offset,uint8_t *bytes, int len)
{
cc_execi(0x90,offset); //MOV DPTR,#data16
for ( int i=0 ; i<len;i++)
{
cc_exec2(0x74,bytes[i]); // MOV A,#data
cc_exec(0xF0); //MOVX @DPTR,A
cc_exec(0xA3); // INC DPTR
}
}

void readPage(int page,uint8_t *buf)
{
uint8_t bank=page>>4;
// get FMAP
uint8_t res = cc_exec2(0xE5, 0xC7);
// select bank
res = (res & 0xF8) | (bank & 0x07);
res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data
// calculer l'adresse de destination
uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset;
// Setup DPTR
cc_execi( 0x90, 0x8000+offset ); // MOV DPTR,#data16
for(int i=0 ; i<2048 ;i++)
{
res = cc_exec ( 0xE0 ); // MOVX A,@DPTR
buf[i] = res;
res = cc_exec ( 0xA3 ); // INC DPTR
}
}

uint8_t verif1[2048];
uint8_t verif2[2048];

int verifPage(int page)
{
do
{
readPage(page,verif1);
readPage(page,verif2);
} while (memcmp(verif1,verif2,2048));
for(int i=Pages[page].minoffset ; i<Pages[page].maxoffset ;i++)
{
if(verif1[i] != Pages[page].datas[i])
{
printf("\nerror at 0x%x, 0x%x instead of 0x%x\n",i,verif1[i],Pages[page].datas[i]);
return 1;
}
}
return 0;
}

int writePage(int page)
{
uint8_t bank=page>>4;
// get FMAP
uint8_t res = cc_exec2(0xE5, 0xC7);
// select bank
res = (res & 0xF8) | (bank & 0x07);
res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data
// calculer l'adresse de destination
uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset;

uint32_t len = Pages[page].maxoffset-Pages[page].minoffset+1;
// configure DMA-0 pour DEBUG --> RAM
uint8_t dma_desc0[8];
dma_desc0[0] = 0x62;// src[15:8]
dma_desc0[1] = 0x60;// src[7:0]
dma_desc0[2] = 0x00;// dest[15:8]
dma_desc0[3] = 0x00;// dest[7:0]
dma_desc0[4] = (len>>8)&0xff;
dma_desc0[5] = (len&0xff);
dma_desc0[6] = 0x1f; //wordsize=0,tmode=0,trig=0x1F
dma_desc0[7] = 0x19;//srcinc=0,destinc=1,irqmask=1,m8=0,priority=1
writeXDATA( 0x1000, dma_desc0, 8 );
cc_exec3( 0x75, 0xD4, 0x00);
cc_exec3( 0x75, 0xD5, 0x10);

// configure DMA-1 pour RAM --> FLASH
uint8_t dma_desc1[8];
dma_desc1[0] = 0x00;// src[15:8]
dma_desc1[1] = 0x00;// src[7:0]
dma_desc1[2] = 0x62;// dest[15:8]
dma_desc1[3] = 0x73;// dest[7:0]
dma_desc1[4] = (len>>8)&0xff;
dma_desc1[5] = (len&0xff);
dma_desc1[6] = 0x12; //wordsize=0,tmode=0,trig=0x12
dma_desc1[7] = 0x42;//srcinc=1,destinc=0,irqmask=1,m8=0,priority=2
writeXDATA( 0x1008, dma_desc1, 8 );
cc_exec3( 0x75, 0xD2, 0x08);
cc_exec3( 0x75, 0xD3, 0x10);
// clear flash status
readXDATA(0x6270, &res, 1);
res &=0x1F;
writeXDATA(0x6270, &res, 1);
// clear DMAIRQ 0 et 1
res = cc_exec2(0xE5, 0xD1);
res &= ~1;
res &= ~2;
cc_exec3(0x75,0xD1,res);
// disarm DMA Channel 0 et 1
res = cc_exec2(0xE5, 0xD6);
res &= ~1;
res &= ~2;
cc_exec3(0x75,0xD6,res);
// Upload to RAM through DMA-0
// arm DMA channel 0 :
res = cc_exec2(0xE5, 0xD6);
res |= 1;
cc_exec3(0x75,0xD6,res);
cc_delay(200);
// transfert de données en mode burst
cc_write(0x80|( (len>>8)&0x7) );
cc_write(len&0xff);
for(int i=0 ; i<len ;i++)
cc_write(Pages[page].datas[i+Pages[page].minoffset]);
// wait DMA end :
do
{
cc_delay(100);
res = cc_exec2(0xE5, 0xD1);
res &= 1;
} while (res==0);
// Clear DMA IRQ flag
res = cc_exec2(0xE5, 0xD1);
res &= ~1;
cc_exec3(0x75,0xD1,res);

// disarm DMA Channel 1
res = cc_exec2(0xE5, 0xD6);
res &= ~2;
cc_exec3(0x75,0xD6,res);
// écrire l'adresse de destination dans FADDRH FADDRL
offset = page<<11 + Pages[page].minoffset;
res=(offset>>2)&0xff;
writeXDATA( 0x6271, &res,1);
res=(offset>>10)&0xff;
writeXDATA( 0x6272, &res,1);
// arm DMA channel 1 :
res = cc_exec2(0xE5, 0xD6);
res |= 2;
cc_exec3(0x75,0xD6,res);
cc_delay(200);
// lancer la copie vers la FLASH
readXDATA(0x6270, &res, 1);
res |= 2;
writeXDATA(0x6270, &res, 1);
// wait DMA end :
do
{
sleep(1);
res = cc_exec2(0xE5, 0xD1);
res &= 2;
} while (res==0);
// vérifie qu'il n'y a pas eu de flash abort
readXDATA(0x6270, &res, 1);
if (res&0x20)
{
fprintf(stderr," flash error !!!\n");
exit(1);
}
}

int main(int argc,char **argv)
{
if( argc <2 ) { fprintf(stderr,"usage : %s file_to_flash\n",argv[0]); exit(1); }
FILE * ficin = fopen(argv[1],"r");
if(!ficin) { fprintf(stderr," Can't open file %s.\n",argv[1]); exit(1); }
// on initialise les ports GPIO et le debugger
cc_init(24,27,28);
// entrée en mode debug
cc_enter();
// envoi de la commande getChipID :
uint16_t ID;
ID = cc_getChipID();
printf(" ID = %04x.\n",ID);

for (int page=0 ; page<128 ; page++)
{
memset(Pages[page].datas,0xff,2048);
Pages[page].minoffset=0xffff;
Pages[page].maxoffset=0;
}
uint16_t ela=0; // extended linear address
uint32_t sla=0; // start linear address
// read hex file
int line=0;
int maxpage=0;
while(fgets(buffer,600,ficin))
{
int sum=0,cksum,type;
uint32_t addr,len;
line++;
if(line%10==0) { printf("\r reading line %d.");fflush(stdout); }
if(buffer[0] != ':') { fprintf(stderr,"incorrect hex file ( : missing)\n"); exit(1); }
if(strlen(buffer)<3 ) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); }
if(!sscanf(buffer+1,"%02x",&len)) { fprintf(stderr,"incorrect hex file (incorrect length\n"); exit(1); }
if(strlen(buffer)<(11 + (len * 2))) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); }
if(!sscanf(buffer+3,"%04x",&addr)) { fprintf(stderr,"incorrect hex file (incorrect addr)\n"); exit(1); }
if(!sscanf(buffer+7,"%02x",&type)) { fprintf(stderr,"incorrect hex file (incorrect record type\n"); exit(1); }
if(type == 4)
{
if(!sscanf(buffer+9,"%04x",&ela)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); }
sla=ela<<16;
continue;
}
if(type == 5)
{
if(!sscanf(buffer+9,"%08x",&sla)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); }
ela = sla>>16;
continue;
}
if(type==1) // EOF
{
break;
}
if(type) { fprintf(stderr,"incorrect hex file (record type %d not implemented\n",type); exit(1); }
sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (type & 255);
int i;
for( i=0 ; i<len ; i++)
{
if(!sscanf(buffer+9+2*i,"%02x",&data[i])) { fprintf(stderr,"incorrect hex file (incorrect data)\n"); exit(1); }
sum+=data[i];
}
if(!sscanf(buffer+9+2*i,"%02x",&cksum)) { fprintf(stderr,"incorrect hex file line %d (incorrect checksum)\n",line); exit(1); }
if ( ((sum & 255) + (cksum & 255)) & 255 ) { fprintf(stderr,"incorrect hex file line %d (bad checksum) %x %x\n",line,(-sum)&255,cksum); exit(1); }
// stock datas
int page= (sla+addr)>>11;
if (page>maxpage) maxpage=page;
uint16_t start=(sla+addr)&0x7ff;
if(start+len> 2048)
{
if (page+1>maxpage) maxpage=page+1;
memcpy(&Pages[page+1].datas[0]
,data,(start+len-2048));
if(0 < Pages[page].minoffset) Pages[page].minoffset=0;
if( (start+len-2048-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-2048-1;
len=2048-start;
}
memcpy(&Pages[page].datas[start]
,data,len);
if(start < Pages[page].minoffset) Pages[page].minoffset=start;
if( (start+len-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-1;
}
printf("\n file loaded (%d lines read).\n",line);


// activer DMA
uint8_t conf=cc_getConfig();
conf &= ~0x4;
cc_setConfig(conf);

for (int page=0 ; page <= maxpage ; page++)
{
if(Pages[page].maxoffset<Pages[page].minoffset) continue;
printf("\rwriting page %3d/%3d.",page+1,maxpage+1);
fflush(stdout);
writePage(page);
}
printf("\n");
// lire les données et les vérifier
int badPage=0;
for (int page=0 ; page <= maxpage ; page++)
{
if(Pages[page].maxoffset<Pages[page].minoffset) continue;
printf("\rverifying page %3d/%3d.",page+1,maxpage+1);
fflush(stdout);
badPage += verifPage(page);
}
printf("\n");
if (!badPage)
printf(" flash OK.\n");
else
printf(" Errors found in %d pages.\n",badPage);

// sortie du mode debug et désactivation :
cc_setActive(false);
fclose(ficin);

}


Loading…
Cancel
Save