📄 an027.c
字号:
//-----------------------------------------------------------------------------------
//
// CYGNAL INTEGRATED PRODUCTS, INC.
//
// FILE NAME : AN027.c
// TARGET DEVICE : C8051F00x
// CREATED ON : 12/01
// CREATED BY : JS
//
// Example code to program a C8051F30x device through its C2 interface.
//
// This software targets a C8051F00x device, though it could be easily
// ported to any Cygnal C8051Fxxx device.
//
// Code assumes the following Port pin connections:
// C8051F0xx: | C8051F30x:
// P1.0 -> C2CK
// P1.1 -> C2D
// VDD -> VDD
// DGND -> GND
//
// Program includes:
// - FLASH programming routines (Block Write, Block Read, Page Erase,
// Device Erase)
// - Primitive C2 communication routines (Address Write, Address Read,
// Data Write, Data Read, Target Reset)
// - Test software for the above routines
//
// Calling sequences for FLASH Programming Routines:
//
// C2 Initialization Procedure:
// 1) Call C2_Reset()
// 2) Call C2_Init()
//
// Note: All following routines assume the C2 Initialization Procedure
// has been executed prior to their calling
//
// Block Read Procedure:
// 1) Set <FLASH_ADDR> to the target FLASH starting address
// 2) Set <NUM_BYTES> to the number of bytes to read
// 3) Initialize the pointer <C2_PTR> to the location to store the
// read data
// 4) Call C2_BlockRead() (will return a '1' if successful,
// '0' otherwise)
//
// Block Write Procedure:
// 1) Set <FLASH_ADDR> to the target FLASH starting address
// 2) Set <NUM_BYTES> to the number of bytes to write
// 3) Initialize the pointer <C2_PTR> to the location of the data
// to be written
// 4) Call C2_BlockWrite() (will return a '1' if successful,
// '0' otherwise)
//
// Page Erase Procedure:
// 1) Set <FLASH_ADDR> to a location within the page to be erased
// 2) Call C2_PageErase()
//
// Device Erase Procedure:
// 1) Call C2_DeviceErase()
//
//-----------------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------------
#include <c8051f000.h> // SFR declarations
#include <stdio.h>
#include <string.h>
//-----------------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------------
// FLASH information
#define FLASH_SIZE 8192 // FLASH size in bytes
#define NUM_PAGES FLASH_SIZE/512 // Number of 512-byte FLASH pages
// C2 status return codes
#define INVALID_COMMAND 0x00
#define COMMAND_FAILED 0x02
#define COMMAND_OK 0x0D
// C2 interface commands
#define GET_VERSION 0x01
#define BLOCK_READ 0x06
#define BLOCK_WRITE 0x07
#define PAGE_ERASE 0x08
#define DEVICE_ERASE 0x03
// C2 Registers
#define FPDAT 0xB4
#define FPCTL 0x02
#define DEVICEID 0x00
#define REVID 0x01
// Program MACROS
#define Poll_OutReady while(!(C2_ReadAR()&0x01))
#define Poll_InBusy while((C2_ReadAR()&0x02))
#define StrobeC2CK C2CK = LOW; C2CK = HIGH
#define C2D_DriverOn PRT1CF |= 0x02 // Configures C2D pin as
// push-pull output
#define C2D_DriverOff PRT1CF &= ~(0x02);P1 |= 0x02 // Configures C2D pin as
// open-drain input
// Misc constants
#define SYSCLK 16000000
#define LOW 0
#define HIGH 1
// C2 Signals
sbit C2CK = P1 ^ 0; // Assign Port pin P1.0 as C2CK
sbit C2D = P1 ^ 1; // Assign Port pin P1.1 as C2D
//-----------------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------------
unsigned char NUM_BYTES;
unsigned int FLASH_ADDR;
unsigned char idata *C2_PTR;
unsigned char idata R_BUF[128];
//-----------------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------------
// FLASH programming functions
void C2_Init();
unsigned char C2_GetDevID(void);
char C2_BlockRead(void);
char C2_BlockWrite(void);
char C2_PageErase(void);
char C2_DeviceErase(void);
// Primitive C2 functions
void C2_Reset(void);
void C2_WriteAR(char);
unsigned char C2_ReadAR(void);
void C2_WriteDR(char);
unsigned char C2_ReadDR(void);
// Utility functions
void Timer3us(unsigned int);
void Port_Init(void);
//-----------------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------------
void main()
{
unsigned int i, j; // Misc. counters
unsigned char W_BUF[] = "Hook 'em!";
WDTCN = 0xDE; // Disable Watchdog Timer
WDTCN = 0xAD;
OSCICN |= 0x03; // Configure internal oscillator for
// highest setting (16MHz)
Port_Init(); // Configure P1.0 as C2CK and P1.1 as C2D
// Read Device ID
C2_Reset(); // Reset target
j = C2_GetDevID(); // Device ID should be 0x04 for 'F30x devices
if (j != 0x04) // Spin here if an 'F30x device is not found
while (1);
// Initiate C2 FLASH Programming
C2_Reset(); // Start with a target device reset
C2_Init(); // Enable FLASH programming via C2
// Erase entire FLASH code space
C2_DeviceErase(); // Erase entire code space
// Read back entire FLASH memory (should be all '1's)
FLASH_ADDR = 0x0000; // Set target addresss (0x0000)
NUM_BYTES = 128; // Set number of bytes to be read
for (i=0;i<60;i++) // Perform 60 128-byte block reads (15 512-byte
{ // FLASH pages, excluding reserved area)
C2_PTR = R_BUF; // Initialize C2 pointer to the read buffer
C2_BlockRead(); // Initiate FLASH read
for (j=0;j<128;j++) // Check read data
{
if (R_BUF[j] != 0xFF)
while (1); // Spin here if any FLASH byte != 0xFF
}
}
// Write FLASH block
FLASH_ADDR = 0x0100; // Set target FLASH address (0x0100)
NUM_BYTES = strlen(W_BUF) + 1; // Set number of bytes to be written (size of
// string stored in W_BUF, +1 for null)
C2_PTR = W_BUF; // Initialize C2 pointer to the target string
C2_BlockWrite(); // Initiate block write
// Read back FLASH block
FLASH_ADDR = 0x0100; // Set target FLASH address
NUM_BYTES = strlen(W_BUF) + 1; // Set number of bytes to be read (size of
// previously written string, +1 for null)
C2_PTR = R_BUF; // Initialize C2 pointer to the read buffer
C2_BlockRead(); // Initiate FLASH read
if (strcmp(R_BUF, W_BUF) != 0) // Compare written string with read data
while (1); // Spin here if strings do not match
// Erase FLASH block
FLASH_ADDR = 0x0100; // Set target FLASH address (page containing
// this address will be erased)
C2_PageErase(); // Perform Erase
// Read back FLASH block
FLASH_ADDR = 0x0100; // Set target FLASH address (0x0100)
NUM_BYTES = strlen(W_BUF) + 1; // Set number of bytes to be read (size of
// previously written string, +1 for null)
C2_PTR = R_BUF; // Initialize C2 pointer to the read buffer
C2_BlockRead(); // Initiate FLASH read
// Check read data (should be all 1's)
for (i=0;i<NUM_BYTES;i++)
{
if (R_BUF[i] != 0xFF) // If read data != 0xFF, an error occured
while (1); // Spin here to indicate error
}
while(1); // Program successful
}
//-----------------------------------------------------------------------------------
// FLASH Programming Routines (High Level)
//-----------------------------------------------------------------------------------
//
// These high-level routines perform the FLASH Programming Interface (FPI)
// command sequences.
//-----------------------------------------------------------------------------------
// C2_Init()
//-----------------------------------------------------------------------------------
// - Initializes the C2 Interface for FLASH programming
//
void C2_Init()
{
C2_Reset(); // Reset the target device
Timer3us(2); // Delay for at least 2us
C2_WriteAR(FPCTL); // Target the C2 FLASH Programming
// Control register (FPCTL) for C2 Data
// register accesses
C2_WriteDR(0x02); // Write the first key code to enable
// C2 FLASH programming
C2_WriteDR(0x01); // Write the second key code to enable
// C2 FLASH programming
Timer3us(20000); // Delay for at least 20ms to ensure the
// target is ready for C2 FLASH programming
}
//-----------------------------------------------------------------------------------
// C2_GetDevID()
//-----------------------------------------------------------------------------------
// - Reads the target Devcie ID register and Revision ID register
//
unsigned char C2_GetDevID()
{
C2_WriteAR(DEVICEID); // Select DeviceID regsiter for C2 Data
// register accesses
return C2_ReadDR(); // Read and return the DeviceID register
}
//-----------------------------------------------------------------------------------
// C2_BlockRead()
//-----------------------------------------------------------------------------------
// - Reads a block of FLASH memory starting at <FLASH_ADDR>
// - The size of the block is defined by <NUM_BYTES>
// - Stores the read data at the location targeted by the pointer <C2_PTR>
// - Assumes that FLASH accesses via C2 have been enabled prior to the function call
// - Function call returns a '1' if successful; returns a '0' if unsuccessful
//
char C2_BlockRead()
{
unsigned char i; // Counter
unsigned char status; // FPI status information holder
C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
// for C2 Data register accesses
C2_WriteDR(BLOCK_READ); // Send FLASH block read command
Poll_InBusy; // Wait for input acknowledge
// Check status before starting FLASH access sequence
Poll_OutReady; // Wait for status information
status = C2_ReadDR(); // Read FLASH programming interface status
if (status != COMMAND_OK)
return 0; // Exit and indicate error
C2_WriteDR(FLASH_ADDR >> 8); // Send address high byte to FPDAT
Poll_InBusy; // Wait for input acknowledge
C2_WriteDR(FLASH_ADDR & 0x00FF); // Send address low byte to FPDAT
Poll_InBusy; // Wait for input acknowledge
C2_WriteDR(NUM_BYTES); // Send block size
Poll_InBusy; // Wait for input acknowledge
// Check status before reading FLASH block
Poll_OutReady; // Wait for status information
status = C2_ReadDR(); // Read FLASH programming interface status
if (status != COMMAND_OK)
return 0; // Exit and indicate error
// Read FLASH block
for (i=0;i<NUM_BYTES;i++)
{
Poll_OutReady; // Wait for data ready indicator
*C2_PTR++ = C2_ReadDR(); // Read data from the FPDAT register
}
return 1; // Exit and indicate success
}
//-----------------------------------------------------------------------------------
// C2_BlockWrite()
//-----------------------------------------------------------------------------------
// - Writes a block of FLASH memory starting at <FLASH_ADDR>
// - The size of the block is defined by <NUM_BYTES>
// - Writes the block stored at the location targetted by <C2_PTR>
// - Assumes that FLASH accesses via C2 have been enabled prior to the function call
// - Function call returns a '1' if successful; returns a '0' if unsuccessful
//
char C2_BlockWrite()
{
unsigned char i; // Counter
unsigned char status; // FPI status information holder
C2_WriteAR(FPDAT); // Select the FLASH Programming Data register
// for C2 Data register accesses
C2_WriteDR(BLOCK_WRITE); // Send FLASH block write command
Poll_InBusy; // Wait for input acknowledge
// Check status before starting FLASH access sequence
Poll_OutReady; // Wait for status information
status = C2_ReadDR(); // Read FLASH programming interface status
if (status != COMMAND_OK)
return 0; // Exit and indicate error
C2_WriteDR(FLASH_ADDR >> 8); // Send address high byte to FPDAT
Poll_InBusy; // Wait for input acknowledge
C2_WriteDR(FLASH_ADDR & 0x00FF); // Send address low byte to FPDAT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -