Şimdi Ara

PICkit2 Programmer to go hafıza çiplerini SPI flash yapma

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
43
Cevap
0
Favori
953
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 123
Sayfaya Git
Git
sonraki
Giriş
Mesaj
  • Merhaba. PICkit v.2.61 yazılımının kaynak kodlarını incelerken gizli kalmış bir özelliği keşfettim. Programmer to Go özelliği SPI flash çiplerini de destekliyormuş. PC tarafındaki yazılım 32Mbit(4MB)'e kadar destek veriyormuş. Ama microchip bu noktada benden bu kadar Firmware kısmını da siz halledin deyip öyle bırakmış.

    Programmer to Go'nun EEPROm arayüzü şu şekilde çalışıyor. Firmware kodlarını inceleyerek çalışma mantığını ortaya çıkardım.

    void PK2GoInit fonksiyonu EEPROM'u hazır hale getiriyor. Gerekli ön hazırlıkları yapıyor.
    void Wr64ToExtEE fonksiyonu her seferinde 64B'lık veri bloklarını EEPROM'a yazıyor.
    void Rd64FromExtEE fonksiyonu her seferinde 64B'lık veri bloklarını EEPROM'dan okuyor.
    void AddrExtEE fonksiyonu okunacak/yazılacak adres bilgisini EEPROM'a gönderiyor.

    Bu üç fonksiyon doğrudan EEPROM ile iletişim sağlıyor. Geri kalan fonksiyonların EEPROM ile doğrudan bir haberleşmesi yok.

    Okuma yazma işlemleri genel olarak şöyle işliyor. PC yazılımının gönderdiği veriyi void WrByteExtEE(unsigned char byteval) fonksiyonu 64Byte'lık bir tampon alanda biriktiriyor. Tampon dolduğunda Wr64ToExtEE fonksiyonu çağırarak biriken verinin EEPROM'a yazılması sağlıyor.

    EEPROM'dan okuma yapılacağı zaman void Rd64FromExtEE fonksiyonu ile okunmuş olan 64B'lık veri bloğu unsigned char RdByteExtEE(void) çağrılarak okunuyor. Tampon alan boş ise void Rd64FromExtEE çağrılarak EEPROM'dan veri okuması yapılıyor.

    Cleaned diye char tipinde bir değişken atadım.
    Cleaned = 0, çip kirli; ;D
    Cleaned = 1, çip temiz, veri yazılabilir.

    Değişkenin başlangıçtaki varsayılan değeri 0 olacak. Wr64ToExtEE fonksiyonu çalıştığında ilk başta bunu kontrol edecek. Çip kirli ise önce bir temizleyecek. Çip temiz ise doğrudan yazmaya geçecek. Bu sayede her seferinde çipi silmesini engelleyeceğim.

    Bir de siz kontrol edebilir misiniz? Kusuru eksiği falan var mı?
    pk_prog2go.c dosyası

    < Bu ileti mini sürüm kullanılarak atıldı >







  • Programmer-To-Go özelliği pickit2 programlayıcısı üzerindeki spi flash a hex dosyasını yazmaya, daha sonrada bilgisayara ihtiyaç olmadan sadece programlayıcıyı powerbank vb bir kaynak ile besleyerek, programlayıcı üzerindeki buton ile diğer mcu ları programlamak için kullanılan bir özellik. Varlığından yıllardır haberdarım ama şimdiye kadar aktif olarak hiç kullanmadım, ofis ortamında pc yazılımını kullanmak daha kolay geliyor PICkit2 Programmer to go hafıza çiplerini SPI flash yapma 


    Pickit2 yazılımında zaten bu özellik var, programlayıcınızda spi flash ve buton bağlantısı varsa extra birşey yapmanıza gerek yok. Siz tam olarak ne yapmak istiyorsunuz, iftar öncesi anlama kabiliyetim biraz azalmış olabilir PICkit2 Programmer to go hafıza çiplerini SPI flash yapma 





  • rafet32 kullanıcısına yanıt
    ICSP üzerinden SPI flash programlamaktan bahsetmiyorum.

    Pickit2 cihazında varsayılan olarak I2C EEPROM'lar var. SPI flash PC tarafındaki yazılımda destekleniyor. Ancak pickit2 firmware yazılımında sadece I2C hafızalara destek var. I2C hafızalar SPI flash hafızalara göre çok pahalılar. Microchip masaüstü yazılımına SPI flash desteği koymuş ama Pickit2 içindeki firmware yazılımına bu desteği eklememiş.

    Ben programmer to go özelliğini SPI flash hafıza ile kullanmak için firmware üzerinde çalışıyorum.



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 16 Mart 2024; 18:41:23 >
    < Bu ileti mini sürüm kullanılarak atıldı >
  • Aynı şeyden bahsediyoruz üstadım. Bende orjinal pickit2 ve pickit3 serileri var içinde yanlış hatırlamıyorsam 2 adet 24c512 eeprom var. Bunlar I2C ile çalışıyor, sizin amacınızı şimdi anladım. I2C yerine SPI arabirimli chip kullanmak istiyorsunuz.


    64 byte sınırı sanırım usb-hid transfer limiti ile ilgili. Çünkü Usb-hid üzerinden bir veri paketi max 64 byte olabilir. İftardan sonra sistemler normale dönünce paylaştığınız dosyayı incelemeye çalışırım. PICkit2 Programmer to go hafıza çiplerini SPI flash yapma 

  • rafet32 kullanıcısına yanıt
    64B sınırı bir problem değil.

    Kodu da buraya atayım.
     
    /*********************************************************************
    *
    * Microchip PICkit 2 v2 Flash Starter Kit
    *
    *********************************************************************
    * FileName: pk_prog2go.c
    * Dependencies: See INCLUDES section below
    * Processor: PIC18
    * Compiler: C18 3.00
    * Company: Microchip Technology, Inc.
    *
    * Software License Agreement
    *
    * The software supplied herewith by Microchip Technology Incorporated
    * (the “Company”) for its PICmicro® Microcontroller is intended and
    * supplied to you, the Company’s customer, for use solely and
    * exclusively on Microchip PICmicro Microcontroller products. The
    * software is owned by the Company and/or its supplier, and is
    * protected under applicable copyright laws. All rights are reserved.
    * Any use in violation of the foregoing restrictions may subject the
    * user to criminal sanctions under applicable laws, as well as to
    * civil liability for the breach of the terms and conditions of this
    * license.
    *
    * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
    * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
    * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
    * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
    * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
    *
    * Author Date Comment
    *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    * Walter Kicinski 2008-Feb-22 Initial Write
    ********************************************************************


    /** I N C L U D E S **********************************************************/
    #include <p18cxxx.h>
    #include "delays.h"
    #include "system\typedefs.h"
    #include "system\usb\usb.h"

    #include "io_cfg.h" // I/O pin mapping
    #include "user\pk_prog2go.h"
    #include "user\pickit.h"
    #include "user\pk_isr.h"




    /** V A R I A B L E S ********************************************************/
    #pragma udata PK2GO=0x4B0
    unsigned char eebuffer_idx;
    unsigned int ext_ee_addr; // in multiples of 64 bytes.

    #define osccal_save_h UARTStatus.TimerBaudLoadH
    #define osccal_save_l UARTStatus.TimerBaudLoadL
    #define checksum_bl_mr UARTStatus.TXbits
    #define bandgap_save_h UARTStatus.LastRXByte

    #pragma udata ExtEE_Buffer=0x4c0 // end of USB RAM //Last state 4C0; 10.03.24 Adem Gdk
    unsigned char eebuffer[64]; // buffer for 64-byte page writes/reads of External EE

    /*//SPI flash komut seti 10.03.24 Adem Gdk
    unsigned int erase_flash=0x60;
    unsigned int write_enable=0x06;
    unsigned int write_flash=0x02;
    unsigned int flash_busy;
    //
    */

    /** P R I V A T E P R O T O T Y P E S ***************************************/

    void Wr64ToExtEE(void);
    void Rd64FromExtEE(void);
    unsigned char AddrExtEE(void);
    char cleaned = 0;
    void WrByteExtEE(unsigned char byteval);
    unsigned char RdByteExtEE(void);
    void ExitLearnMode(void);
    void PK2GoStoreScriptInBuffer(void);
    void CopyScriptToInbuffer(unsigned char len);
    void PK2GoWriteDownloadDataBuffer(void);
    void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h);
    void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h);
    void CalcUploadChecksum(void);
    char CheckDeviceID(void);
    void ReadBandGap(void);
    void WriteCfgBandGap(void);

    /** D E C L A R A T I O N S **************************************************/

    #pragma code


    /******************************************************************************
    * Function: void PK2GoInit(void)
    *
    * Overview: Hardware and Software initializations necessary for
    * Programmer-To-Go functionality
    *
    * PreCondition: None
    *
    * Input: None
    *
    * Output: eebuffer_idx = 0
    * ext_ee_addr = 0
    * pk2go_error_code = 0
    *
    * Side Effects: Sets up MSSP module for Master I2C
    *
    * Note: None
    *****************************************************************************/
    /*
    unsigned int check_busy() //10.03.24 Adem Gdk
    {
    unsigned int busy;
    unsigned int stat;
    nCS = 0;
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x05;
    while(!PIR1bits.SSPIF); //Wait for complete 1 byte transmission /
    nCS = 1;
    while(!PIR1bits.SSPIF); // Wait for complete 1 byte transmission /
    PIR1bits.SSPIF=0; // Clear SSPIF flag
    stat=SSPBUF;
    busy=stat&&0x01;
    return(stat);
    }
    */



    void PK2GoInit(void)
    {
    char i;

    eebuffer_idx = 0;
    ext_ee_addr = 0;
    pk2go_error_code = 0; // no errors

    // Init MSSP module for Master I2C
    SSPCON2 = 0;
    SSPSTAT = 0x00; // SPI master, Input data sampled at middle of data output time,Transmit occurs on transition from Idle to active clock state 16.03.24 Adem Gdk
    SSPCON1 = 0x21; // SSP enabled, SPI master mode, FOSC/16 //09.03.24 Adem Gdk
    //SSPADD = 31; // about 390kHz

    /*
    SSPCON2bits.PEN = 1; //send stop
    while (SSPCON2bits.PEN); //wait for stop
    */ //İptal. 09.03.24 Adem Gdk





    }

    /******************************************************************************
    * Function: void Wr64ToExtEE(void)
    *
    * Overview: Writes the 64 bytes in eebuffer to the external EEPROMs at
    * address ext_ee_addr*64
    *
    * PreCondition: None
    *
    * Input: ext_ee_addr
    * eebuffer = data to write
    *
    * Output: eebuffer_idx = 0
    * ext_ee_addr++
    *
    * Side Effects: Leaves EEPROMS write protected.
    *
    * Note: None
    *****************************************************************************/
    void Wr64ToExtEE(void)
    {

    unsigned char i2c_temp;
    char busy;

    if(!cleaned)
    {
    nCS = 0; //Hafızayı seç. 09.03.24 Adem Gdk
    SSPCON1bits.WCOL = 0;
    PIR1bits.SSPIF = 0;
    SSPBUF = 0x06; //0x06 yazma aktif kodu 10.03.24 //send WREN
    //while(SSPCON1bits.WCOL);
    nCS = 1;

    Delay10KTCYx(3); // 2ms bekle. //16.03.2024 Wait 2ms.

    nCS = 0;
    SSPCON1bits.WCOL = 0; //16.03.2024
    SSPBUF = 0x60; //0x60 SPI silme kodu 10.03.24 Send Bulk Erase
    //while(SSPCON1bits.WCOL);
    nCS = 1;
    SSPCON1bits.WCOL = 0;
    //16.03.2024 Adem Gdk

    Delay10KTCYx(6); // wait 5ms for erase. //Wait 5ms to Erase
    nCS = 0;
    SSPCON1bits.WCOL = 0;
    SSPBUF = 0x05; //Durum kaydını oku; //Read status
    nCS = 1;
    do
    {
    if(PIR1bits.SSPIF = 1)
    {
    SSPBUF = busy;
    PIR1bits.SSPIF = 0;
    }
    }
    while(busy & 0x01); // Busy biti 0 olunca döngüden çık. 16.03.2024 Adem Gdk. Exit loop when busy bit = 0
    busy = 0x00;
    //16.03.2024
    }
    cleaned = 1;
    nCS = 0; // deassert nCS
    SSPCON1bits.WCOL = 0;
    SSPBUF = 0x06;
    nCS = 1;
    nCS = 0;
    SSPCON1bits.WCOL = 0;
    SSPBUF = 0x02;
    AddrExtEE();

    // Send Data
    eebuffer_idx = 0;
    do
    {
    PIR1bits.SSPIF = 0;
    SSPBUF = eebuffer[eebuffer_idx++];
    // wait for it to transmit
    //while (!PIR1bits.SSPIF);

    } while (eebuffer_idx < 64);

    nCS = 1; // assert WP //10.03.24 Adem Gdk

    Delay10KTCYx(2); // wait 5ms for write.
    nCS = 0;
    SSPCON1bits.WCOL = 0;
    SSPBUF = 0x05; //Durum kaydını oku; //Read status
    nCS = 1;
    do
    {
    if(PIR1bits.SSPIF = 1)
    {
    SSPBUF = busy;
    PIR1bits.SSPIF = 0;
    }
    }
    while(busy & 0x01); // Busy biti 0 olunca döngüden çık. 16.03.2024 Adem Gdk. Exit loop when busy bit = 0
    //16.03.2024
    busy = 0x00;
    eebuffer_idx = 0; // reset buffer pointer
    ext_ee_addr++; // inc address.


    }

    /******************************************************************************
    * Function: void Rd64FromExtEE(void)
    *
    * Overview: Reads 64 bytes from the external EEPROMs at address
    * ext_ee_addr*64 into the eebuffer buffer.
    *
    * PreCondition: None
    *
    * Input: ext_ee_addr
    *
    * Output: eebuffer_idx = 0
    * eebuffer = 64 bytes from EEPROM
    * ext_ee_addr++
    *
    * Side Effects: Leaves EEPROMS write protected.
    *
    * Note: None
    *****************************************************************************/
    void Rd64FromExtEE(void)
    {
    // unsigned char i2c_read;

    // i2c_read = AddrExtEE() | 0x01;

    nCS = 0;
    SSPCON1bits.WCOL = 0;
    SSPBUF = 0x03;
    AddrExtEE();


    // Receive Data
    eebuffer_idx = 0;
    do
    {
    PIR1bits.SSPIF = 0;
    while (!PIR1bits.SSPIF); // wait for byte to come in.
    eebuffer[eebuffer_idx++] = SSPBUF; //read byte into USB buffer
    } while (eebuffer_idx < 64);
    nCS = 1;

    eebuffer_idx = 0;
    ext_ee_addr++; // inc address.
    }

    /******************************************************************************
    * Function: unsigned char AddrExtEE(void)
    *
    * Overview: Completes the I2C address byte and 2 EE address bytes
    *
    * PreCondition: None
    *
    * Input: -
    *
    * Output: returns the I2C address byte value
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    unsigned char AddrExtEE(void)
    {
    unsigned char add_l;
    unsigned char add_m;
    unsigned char add_h;
    //unsigned char i2c_addr = 0xA0; // init for I2C control code byte //SPI'da gerek yok.

    //EE adresinin düşük byte'ını oluştur ve gönder.. Generate middle byte of EE addres and send it.
    add_l = (ext_ee_addr << 6) & 0xFF;
    SSPCON1bits.WCOL = 0;
    SSPBUF = add_l;

    //EE adresinin orta byte'ını oluştur. Generate middle byte of EE addres
    add_m = (ext_ee_addr >> 2) & 0xFF;
    //while(SSPCON1bits.WCOL);
    SSPCON1bits.WCOL = 0;
    SSPBUF = add_m;

    //EE adresinin yüksek byte'ını oluştur. Generate high byte of EE addres
    add_m = (ext_ee_addr >> 10) & 0xFF;
    //while(SSPCON1bits.WCOL);
    SSPCON1bits.WCOL = 0;
    SSPBUF =add_h;
    //16.03.2024 Adem Gdk.



    /*
    if (pk2go_memsize == 0)
    { // 2 x 24LC512
    // Check for which EEPROM:
    if (ext_ee_addr & 0x400)
    { // location in upper 64K
    i2c_addr |= 0x2; // Set A0 bit
    }
    }
    else
    { // 2 x 24LC1025
    // Check for which EEPROM:
    if (ext_ee_addr & 0x800)
    { // location in upper 128K
    i2c_addr |= 0x2; // Set A0 bit
    }
    // Check for which Bank:
    if (ext_ee_addr & 0x400)
    { // location in upper bank
    i2c_addr |= 0x8; // Set B0 bit
    }
    }
    */ //İptal. 16.03.2024 Adem Gdk.

    /*
    // Send start bit
    SSPCON2bits.SEN = 1;
    while (SSPCON2bits.SEN); //wait for start

    // Send I2C Control Code
    PIR1bits.SSPIF = 0;
    SSPBUF = i2c_addr;
    // wait for it to transmit
    // generate high EE address while waiting
    i2c_temp = (ext_ee_addr >> 2) & 0xFF;
    while (!PIR1bits.SSPIF);
    if (SSPCON2bits.ACKSTAT)
    { // no acknowledge - abort
    SSPCON2bits.PEN = 1; //send stop
    }
    */ //İptal. 16.03.2024
    /*
    // Send High EE address
    PIR1bits.SSPIF = 0;
    SSPBUF = i2c_temp;
    // wait for it to transmit
    // generate low EE address while waiting
    i2c_temp = (ext_ee_addr << 6) & 0xFF;
    while (!PIR1bits.SSPIF);
    if (SSPCON2bits.ACKSTAT)
    { // no acknowledge - abort
    SSPCON2bits.PEN = 1; //send stop

    }

    // Send Low EE address
    PIR1bits.SSPIF = 0;
    SSPBUF = i2c_temp;
    wait for it to transmit
    while (!PIR1bits.SSPIF);
    if (SSPCON2bits.ACKSTAT)
    { // no acknowledge - abort
    SSPCON2bits.PEN = 1; //send stop
    }

    return i2c_addr;*/
    }

    /******************************************************************************
    * Function: void WrByteExtEE(unsigned char byteval)
    *
    * Overview: Writes a byte to the eebuffer. When 64 bytes are written,
    * Wr64ToExtEE() is called to write them to the external EE
    *
    * PreCondition: None
    *
    * Input: byteval = byte to write
    * eebuffer_idx
    *
    * Output: eebuffer[eebuffer_idx] = byteval
    * eebuffer_idx++
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void WrByteExtEE(unsigned char byteval)
    {
    eebuffer[eebuffer_idx++] = byteval;
    if (eebuffer_idx > 63)
    Wr64ToExtEE();
    }

    /******************************************************************************
    * Function: unsigned char RdByteExtEE(void)
    *
    * Overview: Reads a byte from eebuffer. If eebuffer is empty,
    * Rd64FromExtEE() is called to read from the external EE
    *
    * PreCondition: None
    *
    * Input: byteval = byte to write
    * eebuffer_idx
    *
    * Output: returns eebuffer[eebuffer_idx]
    * eebuffer_idx++
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    unsigned char RdByteExtEE(void)
    {
    if (eebuffer_idx > 63)
    {
    Rd64FromExtEE();
    eebuffer_idx = 0;
    }
    return eebuffer[eebuffer_idx++];
    }

    /******************************************************************************
    * Function: void EnterLearnMode(unsigned char *usbindex)
    *
    * Overview: Checks for key sequence and enters PK2GO Learn mode
    *
    * PreCondition: None
    *
    * Input: *usbindex - index to start address in USB buffer
    *
    * Output: pk2go_memsize
    * PK2Go_Mode
    *
    * Side Effects: Stops normal execution of USB commands
    *
    * Note: None
    *****************************************************************************/
    void EnterLearnMode(unsigned char usbindex)
    {
    PK2Go_Mode = PK2GO_MODE_OFF;

    if (CheckKeySequence(usbindex))
    {
    // set pk2go_memsize
    pk2go_memsize = inbuffer[usbindex + 3];

    PK2Go_Mode = PK2GO_MODE_LEARN;
    PK2GoInit();
    BUSY_LED = 1;
    }
    }

    /******************************************************************************
    * Function: char CheckKeySequence(unsigned char usbindex)
    *
    * Overview: Checks for key sequence
    *
    * PreCondition: None
    *
    * Input: usbindex - index to start address in USB buffer
    *
    * Output: return 1 for correct sequence, 0 otherwise
    *
    * Side Effects:
    *
    * Note: None
    *****************************************************************************/
    char CheckKeySequence(unsigned char usbindex)
    {
    // check for key sequence
    if (inbuffer[usbindex++] != 0x50)
    return 0;

    if (inbuffer[usbindex++] != 0x4B)
    return 0;

    if (inbuffer[usbindex++] != 0x32)
    return 0;

    return 1;
    }

    /******************************************************************************
    * Function: void ExitLearnMode(void)
    *
    * Overview: Completes last EEPROM write and exits mode
    *
    * PreCondition: None
    *
    * Input: eebuffer_idx
    *
    * Output: PK2Go_Mode = PK2GO_MODE_OFF
    *
    * Side Effects: Stops normal execution of USB commands
    *
    * Note: None
    *****************************************************************************/
    void ExitLearnMode(void)
    {
    do // complete last write of eebuffer
    {
    WrByteExtEE(END_OF_BUFFER);
    } while (eebuffer_idx > 0);

    PK2Go_Mode = PK2GO_MODE_OFF;
    BUSY_LED = 0;
    }

    /******************************************************************************
    * Function: void PK2GoLearn(void)
    *
    * Overview: Process a USB packet, storing into external EEPROM
    *
    * PreCondition: PK2GoInit() executed
    *
    * Input: inbuffer
    *
    * Output: None
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void PK2GoLearn(void)
    {
    unsigned char usb_idx = 0; // index of USB buffer
    unsigned char temp = 0;

    do
    {
    switch(inbuffer[usb_idx]) // parse buffer for commands
    {
    case END_OF_BUFFER:
    usb_idx = 64; // ignore the rest of the USB packet.
    break;

    case EXIT_LEARN_MODE: // Exit PK2GO Learn Mode
    // format: 0xB6
    // response: -
    usb_idx = 64; // ignore the rest of the USB packet.
    ExitLearnMode();
    break;

    case WR_INTERNAL_EE: // ignore
    // format: 0xB1 <address><datalength><data1><data2>....<dataN>
    usb_idx+=2;
    usb_idx+= inbuffer[usb_idx] + 1;
    break;

    case RD_INTERNAL_EE: // ignore
    // format: 0xB2 <address><datalength>
    usb_idx+=3;
    break;

    case SETVDD:
    // format: 0xA0 <CCPL><CCPH><VDDLim>
    // response: -
    case SETVPP:
    // format: 0xA1 <CCPR2L><VPPADC><VPPLim>
    // response: -
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    break;

    case SET_VOLTAGE_CALS: // ignore
    // format: 0xB0 <adc_calfactorL><adc_calfactorH><vdd_offset><calfactor>
    // response: -
    usb_idx+=5;
    break;

    case DOWNLOAD_SCRIPT: // Store a script in the Script Buffer
    // format: 0xA4 <Script#><ScriptLengthN><Script1><Script2>....<ScriptN>
    // response: -
    WrByteExtEE(inbuffer[usb_idx++]); // A4
    WrByteExtEE(inbuffer[usb_idx++]); // Script#
    temp = inbuffer[usb_idx++]; // script length
    WrByteExtEE(temp);
    do
    {
    WrByteExtEE(inbuffer[usb_idx++]);
    temp--;
    } while (temp > 0);
    break;

    case EXECUTE_SCRIPT: // immediately executes the included script
    // format: 0xA6 <ScriptLengthN><Script1><Script2>....<ScriptN>
    // response: -
    WrByteExtEE(inbuffer[usb_idx++]); // A6
    temp = inbuffer[usb_idx++]; // ScriptLengthN
    WrByteExtEE(temp);
    do
    {
    WrByteExtEE(inbuffer[usb_idx++]);
    temp--;
    } while (temp > 0);
    break;




    case DOWNLOAD_DATA: // add data to download buffer
    // format: 0xA8 <datalength><data1><data2>....<dataN>
    // response: -
    WrByteExtEE(inbuffer[usb_idx++]); // A8
    temp = inbuffer[usb_idx++]; // datalength
    WrByteExtEE(temp);
    do
    {
    WrByteExtEE(inbuffer[usb_idx++]);
    temp--;
    } while (temp > 0);
    break;

    case CLR_DOWNLOAD_BUFFER: // empties the download buffer
    // format: 0xA7
    // response: -
    case CLR_UPLOAD_BUFFER: // empties the upload buffer
    // format: 0xA9
    // response: -
    case UPLOAD_DATA: // reads data from upload buffer
    // format: 0xAA
    // response: <DataLengthN><data1><data2>....<dataN>
    case CLR_SCRIPT_BUFFER:
    // format: 0xAB
    // response: -
    case UPLOAD_DATA_NOLEN: // reads data from upload buffer
    // format: 0xAC
    // response: <data1><data2>....<dataN>
    // META-COMMANDS--------------------------------
    case READ_BANDGAP: //
    case WRITE_CFG_BANDGAP: //
    WrByteExtEE(inbuffer[usb_idx++]);
    break;

    case READ_STATUS:
    case READ_VOLTAGES: //ignore
    case RESET: // ignore
    // format: 0xAE
    // response: -
    case SCRIPT_BUFFER_CHKSM: // ignore
    usb_idx++;
    break;

    case RUN_SCRIPT: // run a script from the script buffer
    // format: 0xA5 <Script#><iterations>
    // response: -
    // META-COMMANDS--------------------------------
    case START_CHECKSUM: // clear checksum
    case VERIFY_CHECKSUM:
    case CHANGE_CHKSM_FRMT:
    case READ_OSCCAL: // read OSCCAL value
    case WRITE_OSCCAL: // write OSCCAL value
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    break;
    // META-COMMAND---------------------------------
    case CHECK_DEVICE_ID:
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    WrByteExtEE(inbuffer[usb_idx++]);
    break;

    default: // extraneous command
    usb_idx++; // ignore
    } // end switch
    } while (usb_idx < 64); // end DO
    }

    /******************************************************************************
    * Function: void PK2GoExecute(void)
    *
    * Overview: Processes commands and data from external EEPROM
    *
    * PreCondition:
    *
    * Input:
    *
    * Output: None
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void PK2GoExecute(void)
    {
    unsigned char NextCmd;
    unsigned char temp;

    PK2GoInit();
    eebuffer_idx = 64; // force a read on first access

    do
    {
    NextCmd = RdByteExtEE();

    switch(NextCmd)
    {

    // META-COMMANDS--------------------------------
    case READ_OSCCAL: // read OSCCAL value
    temp = RdByteExtEE();
    ReadOSCCAL(temp, RdByteExtEE());
    break;

    case WRITE_OSCCAL: // write OSCCAL value
    temp = RdByteExtEE();
    WriteOSCCAL(temp, RdByteExtEE());
    break;

    case START_CHECKSUM:
    checksum_l = 0;
    checksum_h = 0;
    case CHANGE_CHKSM_FRMT:
    checksum_bl_mr = RdByteExtEE();
    RdByteExtEE(); // 2nd arg is not used
    break;

    case VERIFY_CHECKSUM: // sets checksum to 0 if match.
    checksum_l = ~checksum_l;
    checksum_h = ~checksum_h;
    checksum_l ^= RdByteExtEE();
    checksum_h ^= RdByteExtEE();
    break;

    case CHECK_DEVICE_ID:
    asm_temp5 = RdByteExtEE(); // mask_l
    asm_temp6 = RdByteExtEE(); // mask_h
    asm_temp7 = RdByteExtEE(); // val_l
    asm_temp8 = RdByteExtEE(); // valu_h
    if (!CheckDeviceID())
    {
    pk2go_error_code = 1; // device ID error.
    NextCmd = END_OF_BUFFER; // Stop processing.
    }
    break;

    case READ_BANDGAP:
    ReadBandGap();
    break;

    case WRITE_CFG_BANDGAP:
    WriteCfgBandGap();
    break;

    // NORMAL COMMANDS--------------------------------
    case NO_OPERATION: // Do nothing
    // format: 0x5A
    break;

    case SETVDD:
    // format: 0xA0 <CCPL><CCPH><VDDLim>
    // CCPH:CCPL = ((Vdd * 32) + 10.5) << 6 where Vdd is desired voltage
    // VDDLim = (Vfault / 5) * 255 where Vdd < VFault is error
    // response: -
    temp = RdByteExtEE();
    CalAndSetCCP1(RdByteExtEE(), temp);
    VddVppLevels.VddThreshold = CalThresholdByte(RdByteExtEE()); // Set error threshold
    break;

    case SETVPP:
    // format: 0xA1 <CCPR2L><VPPADC><VPPLim>
    // CCPR2L = duty cycle. Generally = 0x40
    // VPPADC = Vpp * 18.61 where Vpp is desired voltage.
    // VPPlim = Vfault * 18.61 where Vdd < VFault is error
    // response: -
    Vpp_PWM.CCPRSetPoint = RdByteExtEE();
    Vpp_PWM.UppperLimit = CalThresholdByte(RdByteExtEE())+1;
    Vpp_PWM.LowerLimit = Vpp_PWM.UppperLimit - 2;
    VddVppLevels.VppThreshold = CalThresholdByte(RdByteExtEE());
    break;

    case DOWNLOAD_SCRIPT: // Store a script in the Script Buffer
    // format: 0xA4 <Script#><ScriptLengthN><Script1><Script2>....<ScriptN>
    // response: -
    PK2GoStoreScriptInBuffer();
    break;

    case RUN_SCRIPT: // run a script from the script buffer
    // format: 0xA5 <Script#><iterations>
    // response: -
    temp = RdByteExtEE();
    RunScript(temp, RdByteExtEE());
    break;

    case EXECUTE_SCRIPT: // immediately executes the included script
    // format: 0xA6 <ScriptLengthN><Script1><Script2>....<ScriptN>
    // response: -
    temp = RdByteExtEE(); // length
    CopyScriptToInbuffer(temp);
    ScriptEngine(&inbuffer[0], temp);
    break;

    case CLR_DOWNLOAD_BUFFER: // empties the download buffer
    // format: 0xA7
    // response: -
    ClearDownloadBuffer();
    break;

    case DOWNLOAD_DATA: // add data to download buffer
    // format: 0xA8 <datalength><data1><data2>....<dataN>
    // response: -
    PK2GoWriteDownloadDataBuffer();
    break;

    case CLR_UPLOAD_BUFFER: // empties the upload buffer
    // format: 0xA9
    // response: -
    ClearUploadBuffer();
    break;

    case UPLOAD_DATA_NOLEN: // reads data from upload buffer
    case UPLOAD_DATA: // reads data from upload buffer
    // format: 0xAA
    // response: <DataLengthN><data1><data2>....<dataN>
    CalcUploadChecksum();
    break;

    case CLR_SCRIPT_BUFFER:
    // format: 0xAB
    // response: -
    ClearScriptTable();
    break;

    default: // End of Buffer or unrecognized command
    NextCmd = END_OF_BUFFER; // Stop processing.
    } // end switch
    } while(NextCmd != END_OF_BUFFER);

    }

    /******************************************************************************
    * Function: char CheckDeviceID(void)
    *
    * Overview: Reads and checks the target Device ID
    *
    * PreCondition: None
    *
    * Input: asm_temp2/1 = deviceID mask
    * asm_temp4/3 = deviceID value
    *
    * Output: returns 1 if device ID matches, 0 if not
    *
    * Side Effects:
    *
    * Note: None
    *****************************************************************************/
    char CheckDeviceID(void)
    {
    // clear upload buffer
    ClearUploadBuffer();
    RunScript(0, 1); // program entry
    RunScript(2, 1); // Read Device ID
    RunScript(1, 1); // program exit
    // apply mask
    asm_temp5 &= uc_upload_buffer[uploadbuf_mgmt.read_index++];
    asm_temp6 &= uc_upload_buffer[uploadbuf_mgmt.read_index++];
    // reclear upload buffer
    ClearUploadBuffer();
    // check value
    if ((asm_temp5 == asm_temp7) && (asm_temp6 == asm_temp8))
    {
    return 1; // pass
    }
    return 0; //fail
    }

    /******************************************************************************
    * Function: void CalcUploadChecksum(void)
    *
    * Overview: Adds the bytes in the Upload buffer to checksum_h\l
    *
    * PreCondition: None
    *
    * Input: checksum_h\l
    *
    * Output: checksum_h\l
    *
    * Side Effects: Empties Upload buffer
    *
    * Note: None
    *****************************************************************************/
    void CalcUploadChecksum(void)
    {
    unsigned int *checksum = &checksum_l;
    unsigned char i, temp;

    for (i = 0; i < uploadbuf_mgmt.used_bytes; i++)
    {
    temp = uc_upload_buffer[uploadbuf_mgmt.read_index++];
    if (checksum_bl_mr)
    { // clear start/stop bits.
    if (i & 0x1)
    {
    if (checksum_bl_mr & 0x01)
    temp &= 0x7F; // flash
    else
    temp &= 0x01; // eeprom
    }
    else
    temp &= 0xFE;
    }
    *checksum += temp;
    }

    ClearUploadBuffer();

    }

    /******************************************************************************
    * Function: void ReadBandGap(void)
    *
    * Overview: Reads Badgap from target device config word
    *
    * PreCondition: None
    *
    * Input: None
    *
    * Output: bandgap_save_h (masked with 0x30 unshifted)
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void ReadBandGap(void)
    {
    // clear upload buffer
    ClearUploadBuffer();
    RunScript(0, 1); // program entry
    RunScript(13, 1); // CONFIG_RD Read
    RunScript(1, 1); // program exit
    bandgap_save_h = uc_upload_buffer[1] & 0x60;
    // reclear upload buffer
    ClearUploadBuffer();
    }

    /******************************************************************************
    * Function: void WriteCfgBandGap(void)
    *
    * Overview: Writes config word (expected in DL buffer)
    * with bandgap_save_h OR'd in. Expects
    * that prog entry / exit are in DL stream.
    *
    * PreCondition: config word in buffer must have all BG bits set to 0
    *
    * Input: bandgap_save_h
    *
    * Output: None
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void WriteCfgBandGap(void)
    {
    uc_download_buffer[1] |= bandgap_save_h;
    RunScript(15, 1); // CONFIG_WR
    }

    /******************************************************************************
    * Function: void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h)
    *
    * Overview: Reads OSCCAL from target device
    *
    * PreCondition: None
    *
    * Input: addr_l, addr_h = OSCCAL address
    *
    * Output: osccal_save_x
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h)
    {
    // clear download buffer
    ClearDownloadBuffer();
    // clear upload buffer
    ClearUploadBuffer();
    // Put address in DL buffer
    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_l;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_h;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = 0;
    downloadbuf_mgmt.used_bytes += 3;
    RunScript(0, 1); // program entry
    RunScript(20, 1); // OSCCAL Read
    RunScript(1, 1); // program exit
    osccal_save_l = uc_upload_buffer[uploadbuf_mgmt.read_index++];
    osccal_save_h = uc_upload_buffer[uploadbuf_mgmt.read_index++];
    // reclear upload buffer
    ClearUploadBuffer();
    }

    /******************************************************************************
    * Function: void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h)
    *
    * Overview: Writes saved OSCCAL from target device
    *
    * PreCondition: None
    *
    * Input: addr_l, addr_h = OSCCAL address
    *
    * Output:
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h)
    {
    // clear download buffer
    ClearDownloadBuffer();
    // clear upload buffer
    ClearUploadBuffer();
    // Put address & osccal in DL buffer
    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_l;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_h;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = 0;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = osccal_save_l;
    uc_download_buffer[downloadbuf_mgmt.write_index++] = osccal_save_h;
    downloadbuf_mgmt.used_bytes += 5;
    RunScript(0, 1); // program entry
    RunScript(21, 1); // OSCCAL write
    RunScript(1, 1); // program exit
    }

    /******************************************************************************
    * Function: void PK2GoStoreScriptInBuffer(void)
    *
    * Overview: Stores the script from eebuffer into Script Buffer & updates
    * the Script Table.
    * Prior script at the given script # is deleted and all following
    * scripts are moved up. New script is appended at end.
    *
    * PreCondition: None
    *
    * Input:
    *
    * Output: uc_script_buffer[] - updated
    * ScriptTable[] - updated
    * Pk2Status.ScriptBufOvrFlow - set if script length > remaining buffer
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void PK2GoStoreScriptInBuffer(void)
    {
    int i;
    int LengthOfAllScripts;
    int Temp_1, Temp_2, Length;

    Temp_2 = RdByteExtEE(); // Script# of new script
    Temp_1 = RdByteExtEE(); // Length of new script
    Length = Temp_1;

    // First, make sure script length is valid
    if (Temp_1 > SCRIPT_MAXLEN)
    {
    Pk2Status.ScriptBufOvrFlow = 1; // set error - script longer than max allowed
    return;
    }

    // calculate length of all scripts.
    LengthOfAllScripts = 0;
    for (i=0; i < SCRIPT_ENTRIES; i++)
    {
    LengthOfAllScripts += ScriptTable[i].Length;
    }
    LengthOfAllScripts -= ScriptTable[Temp_2].Length; // don't count length of script being replaced
    if (Temp_1 > (SCRIPTBUFSPACE-LengthOfAllScripts)) // if there isn't enough room
    {
    Pk2Status.ScriptBufOvrFlow = 1; // set error - not enough room in script buffer
    return;
    }

    // Next, make sure script# is valid
    if (Temp_2 > (SCRIPT_ENTRIES-1)) // 0-31 valid
    {
    Pk2Status.ScriptBufOvrFlow = 1; // set error - script# invalid
    return;
    }


    if (ScriptTable[Temp_2].Length != 0) // If a script exists in that location
    {
    // Move space created by deleting existing script to end of buffer.
    Temp_1 = (SCRIPTBUFSPACE - ScriptTable[Temp_2].Length) - 1; // last copy location.
    for (i=ScriptTable[Temp_2].StartIndex; i < Temp_1; i++)
    {
    *(uc_ScriptBuf_ptr + i) = *(uc_ScriptBuf_ptr + ScriptTable[Temp_2].Length + i);
    }
    // update script table entries
    for (i=0; i < SCRIPT_ENTRIES; i++)
    {
    if (ScriptTable[i].StartIndex > ScriptTable[Temp_2].StartIndex) // if script is in moved section
    {
    ScriptTable[i].StartIndex -= ScriptTable[Temp_2].Length; // adjust by amount moved
    }
    }
    }

    // Store new script at end of buffer
    ScriptTable[Temp_2].Length = Length; // update Script Table Entry with new length.
    ScriptTable[Temp_2].StartIndex = LengthOfAllScripts; // update entry with new index at end of buffer.
    for (i = 0; i < ScriptTable[Temp_2].Length; i++)
    {
    *(uc_ScriptBuf_ptr + LengthOfAllScripts + i) = RdByteExtEE();
    }

    } // end void StoreScriptInBuffer

    /******************************************************************************
    * Function: void CopyScriptToInbuffer(unsigned char len)
    *
    * Overview: Stores the script from eebuffer into the inbuffer
    *
    * PreCondition: None
    *
    * Input:
    *
    * Output: inbuffer = script
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void CopyScriptToInbuffer(unsigned char len)
    {
    unsigned char i;

    for (i = 0; i < len; i++)
    {
    inbuffer[i]= RdByteExtEE();
    }
    }

    /******************************************************************************
    * Function: void PK2GoWriteDownloadDataBuffer(void)
    *
    * Overview: Writes a given # of bytes into the data download buffer.
    *
    * PreCondition: None
    *
    * Input:
    *
    * Output: uc_download_buffer[] - updated with new data
    * downloadbuf_mgmt.write_index - incremented by length of data stored.
    * downloadbuf_mgmt.used_bytes - incremented by length of data stored.
    * Pk2Status.DownloadOvrFlow - set if data length > remaining buffer
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void PK2GoWriteDownloadDataBuffer(void)
    {
    unsigned int i, numbytes;

    numbytes = RdByteExtEE() & 0xFF; // i= # bytes data (length)

    if ((numbytes + downloadbuf_mgmt.used_bytes) > DOWNLOAD_SIZE) // not enough room for data
    {
    Pk2Status.DownloadOvrFlow = 1;
    return;
    }

    for (i = 0; i < numbytes; i++)
    {
    uc_download_buffer[downloadbuf_mgmt.write_index++] = RdByteExtEE();
    if (downloadbuf_mgmt.write_index >= DOWNLOAD_SIZE) // handle index wrap
    {
    downloadbuf_mgmt.write_index = 0;
    }
    downloadbuf_mgmt.used_bytes++; // used another byte.
    }
    } // end void PK2GoWriteDownloadDataBuffer(void)

    /******************************************************************************
    * Function: void Pk2GoErrorBlink(unsigned char blinksX2)
    *
    * Overview: Blinks the BUSY LED for the given # of blinks until
    * the pushbutton is pressed
    *
    * PreCondition: None
    *
    * Input: blinksX2 = twice the # of blinks in sequence
    *
    * Output:
    *
    * Side Effects: None
    *
    * Note: None
    *****************************************************************************/
    void Pk2GoErrorBlink(unsigned char blinksX2)
    {
    char i = 0;

    while(PROG_SWITCH_pin)
    {
    if (i <= blinksX2)
    BUSY_LED = i++ & 0x1;
    else
    i = 0;
    Delay10KTCYx(240); // 200ms
    }
    }



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 16 Mart 2024; 18:59:21 >
    < Bu ileti mini sürüm kullanılarak atıldı >




  • Kodda bir geliştirme daha yaptım.

    AddrExtEE() fonksiyonunu değer döndürür hale getirdim. Fonksiyona istenen byte gönderildiğinde ext_ee_addr'den ilgili byte'ı hesaplayıp geriye döndürecek.

    low byte = 0;

    medium byte = 1;

    high byte = 2;


    olarak parametre belirledim.


    Okuma ve yazma fonksiyonları içinde üç farklı 8 bitlik değişken atadım.

    add_l;

    add_m;

    add_h;


    Okuma/yazma yapılmadan önce adres bilgisi alınarak yukarıdaki değişkenlere atılacak, adres bilgisi byte'lara bölünmüş şekilde önceden hazır olacak.Kesintisiz bir şekilde adres ve veri bilgisi arada duraksama olmadan iletilecek.


    Bu sayede veri akışının adres hesaplaması nedeniyle kesintiye uğramasını da engellemiş olurum. Bu sayede adres ve veriyi önceden hazır halde tutarak iletişim hızını da artırabilirim.

    Orjinal kodda low adres hesaplanıp gönderiliyor ardından high adres hesaplanıp gönderiliyordu. I2C iletişimi zeten yavaş olduğundan arada adres hesaplaması için akışı bölmek sorun yaratmıyordu.


    I2C iletişiminde EEPROM çiplerinin kendi adreslerini de bus üzerinden göndermek gerektiği için AddrExtEE fonksiyonunda karmaşık bir kod çalışıyordu. SPI veriyolunda Çip seçimi CS pini ile yapıldığı için bus üzerinde I2C'deki gibi cihaz adresi gönderme olayı olmadığından, AddrExtEE fonksiyonumuzun sadece okuma/yazma yapılacak adresleri döndürmesi yeterlidir.





    /*********************************************************************

    *

    * Microchip PICkit 2 v2 Flash Starter Kit

    *

    *********************************************************************

    * FileName: pk_prog2go.c

    * Dependencies: See INCLUDES section below

    * Processor: PIC18

    * Compiler: C18 3.00

    * Company: Microchip Technology, Inc.

    *

    * Software License Agreement

    *

    * The software supplied herewith by Microchip Technology Incorporated

    * (the “Company”) for its PICmicro® Microcontroller is intended and

    * supplied to you, the Company’s customer, for use solely and

    * exclusively on Microchip PICmicro Microcontroller products. The

    * software is owned by the Company and/or its supplier, and is

    * protected under applicable copyright laws. All rights are reserved.

    * Any use in violation of the foregoing restrictions may subject the

    * user to criminal sanctions under applicable laws, as well as to

    * civil liability for the breach of the terms and conditions of this

    * license.

    *

    * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,

    * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED

    * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A

    * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,

    * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR

    * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.

    *

    * Author Date Comment

    *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    * Walter Kicinski 2008-Feb-22 Initial Write

    ********************************************************************



    /** I N C L U D E S **********************************************************/

    #include <p18cxxx.h>

    #include "delays.h"

    #include "system\typedefs.h"

    #include "system\usb\usb.h"


    #include "io_cfg.h" // I/O pin mapping

    #include "user\pk_prog2go.h"

    #include "user\pickit.h"

    #include "user\pk_isr.h"





    /** V A R I A B L E S ********************************************************/

    #pragma udata PK2GO=0x4B0

    unsigned char eebuffer_idx;

    unsigned int ext_ee_addr; // in multiples of 64 bytes.


    #define osccal_save_h UARTStatus.TimerBaudLoadH

    #define osccal_save_l UARTStatus.TimerBaudLoadL

    #define checksum_bl_mr UARTStatus.TXbits

    #define bandgap_save_h UARTStatus.LastRXByte


    #pragma udata ExtEE_Buffer=0x4c0 // end of USB RAM //Last state 4C0; 10.03.24 Adem Gdk

    unsigned char eebuffer[64]; // buffer for 64-byte page writes/reads of External EE


    /*//SPI flash komut seti 10.03.24 Adem Gdk

    unsigned int erase_flash=0x60;

    unsigned int write_enable=0x06;

    unsigned int write_flash=0x02;

    unsigned int flash_busy;

    //

    */


    /** P R I V A T E P R O T O T Y P E S ***************************************/


    void Wr64ToExtEE(void);

    void Rd64FromExtEE(void);

    unsigned char AddrExtEE(unsigned char address); //17.3.2024 Adem Gdk

    char cleaned = 0;

    void WrByteExtEE(unsigned char byteval);

    unsigned char RdByteExtEE(void);

    void ExitLearnMode(void);

    void PK2GoStoreScriptInBuffer(void);

    void CopyScriptToInbuffer(unsigned char len);

    void PK2GoWriteDownloadDataBuffer(void);

    void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h);

    void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h);

    void CalcUploadChecksum(void);

    char CheckDeviceID(void);

    void ReadBandGap(void);

    void WriteCfgBandGap(void);


    /** D E C L A R A T I O N S **************************************************/


    #pragma code



    /******************************************************************************

    * Function: void PK2GoInit(void)

    *

    * Overview: Hardware and Software initializations necessary for

    * Programmer-To-Go functionality

    *

    * PreCondition: None

    *

    * Input: None

    *

    * Output: eebuffer_idx = 0

    * ext_ee_addr = 0

    * pk2go_error_code = 0

    *

    * Side Effects: Sets up MSSP module for Master I2C

    *

    * Note: None

    *****************************************************************************/

    /*

    unsigned int check_busy() //10.03.24 Adem Gdk

    {

    unsigned int busy;

    unsigned int stat;

    nCS = 0;

    PIR1bits.SSPIF = 0;

    SSPBUF = 0x05;

    while(!PIR1bits.SSPIF); //Wait for complete 1 byte transmission /

    nCS = 1;

    while(!PIR1bits.SSPIF); // Wait for complete 1 byte transmission /

    PIR1bits.SSPIF=0; // Clear SSPIF flag

    stat=SSPBUF;

    busy=stat&&0x01;

    return(stat);

    }

    */




    void PK2GoInit(void)

    {

    char i;


    eebuffer_idx = 0;

    ext_ee_addr = 0;

    pk2go_error_code = 0; // no errors


    // Init MSSP module for Master I2C

    SSPCON2 = 0;

    SSPSTAT = 0x00; // SPI master, Input data sampled at middle of data output time,Transmit occurs on transition from Idle to active clock state 16.03.24 Adem Gdk

    SSPCON1 = 0x21; // SSP enabled, SPI master mode, FOSC/16 //09.03.24 Adem Gdk

    //SSPADD = 31; // about 390kHz


    /*

    SSPCON2bits.PEN = 1; //send stop

    while (SSPCON2bits.PEN); //wait for stop

    */ //İptal. 09.03.24 Adem Gdk






    }


    /******************************************************************************

    * Function: void Wr64ToExtEE(void)

    *

    * Overview: Writes the 64 bytes in eebuffer to the external EEPROMs at

    * address ext_ee_addr*64

    *

    * PreCondition: None

    *

    * Input: ext_ee_addr

    * eebuffer = data to write

    *

    * Output: eebuffer_idx = 0

    * ext_ee_addr++

    *

    * Side Effects: Leaves EEPROMS write protected.

    *

    * Note: None

    *****************************************************************************/

    void Wr64ToExtEE(void)

    {


    unsigned char i2c_temp;

    char busy;

    unsigned char add_l; //17.03.2024 Adem Gdk

    unsigned char add_m;

    unsigned char add_h;


    if(!cleaned)

    {

    nCS = 0; //Hafızayı seç. 09.03.24 Adem Gdk

    SSPCON1bits.WCOL = 0;

    PIR1bits.SSPIF = 0;

    SSPBUF = 0x06; //0x06 yazma aktif kodu 10.03.24 //send WREN

    //while(SSPCON1bits.WCOL);

    nCS = 1;


    Delay10KTCYx(3); // 2ms bekle. //16.03.2024 Wait 2ms.


    nCS = 0;

    SSPCON1bits.WCOL = 0; //16.03.2024

    SSPBUF = 0x60; //0x60 SPI silme kodu 10.03.24 Send Bulk Erase

    //while(SSPCON1bits.WCOL);

    nCS = 1;

    SSPCON1bits.WCOL = 0;

    //16.03.2024 Adem Gdk


    Delay10KTCYx(6); // wait 5ms for erase. //Wait 5ms to Erase

    nCS = 0;

    SSPCON1bits.WCOL = 0;

    SSPBUF = 0x05; //Durum kaydını oku; //Read status

    nCS = 1;

    do

    {

    if(PIR1bits.SSPIF = 1)

    {

    SSPBUF = busy;

    PIR1bits.SSPIF = 0;

    }

    }

    while(busy & 0x01); // Busy biti 0 olunca döngüden çık. 16.03.2024 Adem Gdk. Exit loop when busy bit = 0

    busy = 0x00;

    //16.03.2024

    }

    cleaned = 1;

    nCS = 0; // deassert nCS

    //Adresleri oluştur. 17.03.2024 Adem Gdk

    add_l = AddrExtEE(0); //Low adresi oluştur.

    add_m = AddrExtEE(1); //Medium adresi oluştur.

    add_h = AddrExtEE(2); //High adresi oluştur.

    SSPCON1bits.WCOL = 0;

    SSPBUF = 0x06;

    nCS = 1;

    nCS = 0;

    SSPCON1bits.WCOL = 0;

    SSPBUF = 0x02;

    //AddrExtEE();

    SSPBUF = add_l;

    SSPBUF = add_m;

    SSPBUF = add_h;

    // Send Data

    eebuffer_idx = 0;

    do

    {

    PIR1bits.SSPIF = 0;

    SSPBUF = eebuffer[eebuffer_idx++];

    // wait for it to transmit

    //while (!PIR1bits.SSPIF);


    } while (eebuffer_idx < 64);


    nCS = 1; // assert WP //10.03.24 Adem Gdk


    Delay10KTCYx(2); // wait 5ms for write.

    nCS = 0;

    SSPCON1bits.WCOL = 0;

    SSPBUF = 0x05; //Durum kaydını oku; //Read status

    nCS = 1;

    do

    {

    if(PIR1bits.SSPIF = 1)

    {

    SSPBUF = busy;

    PIR1bits.SSPIF = 0;

    }

    }

    while(busy & 0x01); // Busy biti 0 olunca döngüden çık. 16.03.2024 Adem Gdk. Exit loop when busy bit = 0

    //16.03.2024

    busy = 0x00;

    eebuffer_idx = 0; // reset buffer pointer

    ext_ee_addr++; // inc address.



    }


    /******************************************************************************

    * Function: void Rd64FromExtEE(void)

    *

    * Overview: Reads 64 bytes from the external EEPROMs at address

    * ext_ee_addr*64 into the eebuffer buffer.

    *

    * PreCondition: None

    *

    * Input: ext_ee_addr

    *

    * Output: eebuffer_idx = 0

    * eebuffer = 64 bytes from EEPROM

    * ext_ee_addr++

    *

    * Side Effects: Leaves EEPROMS write protected.

    *

    * Note: None

    *****************************************************************************/

    void Rd64FromExtEE(void)

    {

    // unsigned char i2c_read;


    // i2c_read = AddrExtEE() | 0x01;


    unsigned char add_l; //17.03.2024 Adem Gdk

    unsigned char add_m;

    unsigned char add_h;


    //Adresleri oluştur. 17.03.2024 Adem Gdk

    add_l = AddrExtEE(0); //Low adresi oluştur.

    add_m = AddrExtEE(1); //Medium adresi oluştur.

    add_h = AddrExtEE(2); //High adresi oluştur.


    nCS = 0;

    SSPCON1bits.WCOL = 0;

    SSPBUF = 0x03;

    //AddrExtEE();

    SSPBUF = add_l; //Adresleri gönder.

    SSPBUF = add_m;

    SSPBUF = add_h;


    // Receive Data

    eebuffer_idx = 0;

    do

    {

    PIR1bits.SSPIF = 0;

    while (!PIR1bits.SSPIF); // wait for byte to come in.

    eebuffer[eebuffer_idx++] = SSPBUF; //read byte into USB buffer

    } while (eebuffer_idx < 64);

    nCS = 1;


    eebuffer_idx = 0;

    ext_ee_addr++; // inc address.

    }


    /******************************************************************************

    * Function: unsigned char AddrExtEE(void)

    *

    * Overview: Completes the I2C address byte and 2 EE address bytes

    *

    * PreCondition: None

    *

    * Input: -

    *

    * Output: returns the I2C address byte value

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    unsigned char AddrExtEE(unsigned char address)

    {

    unsigned char add;

    //unsigned char i2c_addr = 0xA0; // init for I2C control code byte //SPI'da gerek yok.


    //EE adresinin düşük byte'ını oluştur. Generate low byte of EE addres

    if(address == 0)

    {

    add = (ext_ee_addr << 6) & 0xFF;

    }



    //EE adresinin orta byte'ını oluştur. Generate middle byte of EE addres


    if(address == 1)

    {

    add = (ext_ee_addr >> 2) & 0xFF;

    }



    //EE adresinin yüksek byte'ını oluştur. Generate high byte of EE addres

    if(address == 2)

    {

    add = (ext_ee_addr >> 10) & 0xFF;

    }


    return add;

    //16.03.2024 Adem Gdk.




    /*

    if (pk2go_memsize == 0)

    { // 2 x 24LC512

    // Check for which EEPROM:

    if (ext_ee_addr & 0x400)

    { // location in upper 64K

    i2c_addr |= 0x2; // Set A0 bit

    }

    }

    else

    { // 2 x 24LC1025

    // Check for which EEPROM:

    if (ext_ee_addr & 0x800)

    { // location in upper 128K

    i2c_addr |= 0x2; // Set A0 bit

    }

    // Check for which Bank:

    if (ext_ee_addr & 0x400)

    { // location in upper bank

    i2c_addr |= 0x8; // Set B0 bit

    }

    }

    */ //İptal. 16.03.2024 Adem Gdk.


    /*

    // Send start bit

    SSPCON2bits.SEN = 1;

    while (SSPCON2bits.SEN); //wait for start


    // Send I2C Control Code

    PIR1bits.SSPIF = 0;

    SSPBUF = i2c_addr;

    // wait for it to transmit

    // generate high EE address while waiting

    i2c_temp = (ext_ee_addr >> 2) & 0xFF;

    while (!PIR1bits.SSPIF);

    if (SSPCON2bits.ACKSTAT)

    { // no acknowledge - abort

    SSPCON2bits.PEN = 1; //send stop

    }

    */ //İptal. 16.03.2024

    /*

    // Send High EE address

    PIR1bits.SSPIF = 0;

    SSPBUF = i2c_temp;

    // wait for it to transmit

    // generate low EE address while waiting

    i2c_temp = (ext_ee_addr << 6) & 0xFF;

    while (!PIR1bits.SSPIF);

    if (SSPCON2bits.ACKSTAT)

    { // no acknowledge - abort

    SSPCON2bits.PEN = 1; //send stop


    }


    // Send Low EE address

    PIR1bits.SSPIF = 0;

    SSPBUF = i2c_temp;

    wait for it to transmit

    while (!PIR1bits.SSPIF);

    if (SSPCON2bits.ACKSTAT)

    { // no acknowledge - abort

    SSPCON2bits.PEN = 1; //send stop

    }


    return i2c_addr;*/

    }


    /******************************************************************************

    * Function: void WrByteExtEE(unsigned char byteval)

    *

    * Overview: Writes a byte to the eebuffer. When 64 bytes are written,

    * Wr64ToExtEE() is called to write them to the external EE

    *

    * PreCondition: None

    *

    * Input: byteval = byte to write

    * eebuffer_idx

    *

    * Output: eebuffer[eebuffer_idx] = byteval

    * eebuffer_idx++

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void WrByteExtEE(unsigned char byteval)

    {

    eebuffer[eebuffer_idx++] = byteval;

    if (eebuffer_idx > 63)

    Wr64ToExtEE();

    }


    /******************************************************************************

    * Function: unsigned char RdByteExtEE(void)

    *

    * Overview: Reads a byte from eebuffer. If eebuffer is empty,

    * Rd64FromExtEE() is called to read from the external EE

    *

    * PreCondition: None

    *

    * Input: byteval = byte to write

    * eebuffer_idx

    *

    * Output: returns eebuffer[eebuffer_idx]

    * eebuffer_idx++

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    unsigned char RdByteExtEE(void)

    {

    if (eebuffer_idx > 63)

    {

    Rd64FromExtEE();

    eebuffer_idx = 0;

    }

    return eebuffer[eebuffer_idx++];

    }


    /******************************************************************************

    * Function: void EnterLearnMode(unsigned char *usbindex)

    *

    * Overview: Checks for key sequence and enters PK2GO Learn mode

    *

    * PreCondition: None

    *

    * Input: *usbindex - index to start address in USB buffer

    *

    * Output: pk2go_memsize

    * PK2Go_Mode

    *

    * Side Effects: Stops normal execution of USB commands

    *

    * Note: None

    *****************************************************************************/

    void EnterLearnMode(unsigned char usbindex)

    {

    PK2Go_Mode = PK2GO_MODE_OFF;


    if (CheckKeySequence(usbindex))

    {

    // set pk2go_memsize

    pk2go_memsize = inbuffer[usbindex + 3];


    PK2Go_Mode = PK2GO_MODE_LEARN;

    PK2GoInit();

    BUSY_LED = 1;

    }

    }


    /******************************************************************************

    * Function: char CheckKeySequence(unsigned char usbindex)

    *

    * Overview: Checks for key sequence

    *

    * PreCondition: None

    *

    * Input: usbindex - index to start address in USB buffer

    *

    * Output: return 1 for correct sequence, 0 otherwise

    *

    * Side Effects:

    *

    * Note: None

    *****************************************************************************/

    char CheckKeySequence(unsigned char usbindex)

    {

    // check for key sequence

    if (inbuffer[usbindex++] != 0x50)

    return 0;


    if (inbuffer[usbindex++] != 0x4B)

    return 0;


    if (inbuffer[usbindex++] != 0x32)

    return 0;


    return 1;

    }


    /******************************************************************************

    * Function: void ExitLearnMode(void)

    *

    * Overview: Completes last EEPROM write and exits mode

    *

    * PreCondition: None

    *

    * Input: eebuffer_idx

    *

    * Output: PK2Go_Mode = PK2GO_MODE_OFF

    *

    * Side Effects: Stops normal execution of USB commands

    *

    * Note: None

    *****************************************************************************/

    void ExitLearnMode(void)

    {

    do // complete last write of eebuffer

    {

    WrByteExtEE(END_OF_BUFFER);

    } while (eebuffer_idx > 0);


    PK2Go_Mode = PK2GO_MODE_OFF;

    BUSY_LED = 0;

    }


    /******************************************************************************

    * Function: void PK2GoLearn(void)

    *

    * Overview: Process a USB packet, storing into external EEPROM

    *

    * PreCondition: PK2GoInit() executed

    *

    * Input: inbuffer

    *

    * Output: None

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void PK2GoLearn(void)

    {

    unsigned char usb_idx = 0; // index of USB buffer

    unsigned char temp = 0;


    do

    {

    switch(inbuffer[usb_idx]) // parse buffer for commands

    {

    case END_OF_BUFFER:

    usb_idx = 64; // ignore the rest of the USB packet.

    break;


    case EXIT_LEARN_MODE: // Exit PK2GO Learn Mode

    // format: 0xB6

    // response: -

    usb_idx = 64; // ignore the rest of the USB packet.

    ExitLearnMode();

    break;


    case WR_INTERNAL_EE: // ignore

    // format: 0xB1 <address><datalength><data1><data2>....<dataN>

    usb_idx+=2;

    usb_idx+= inbuffer[usb_idx] + 1;

    break;


    case RD_INTERNAL_EE: // ignore

    // format: 0xB2 <address><datalength>

    usb_idx+=3;

    break;


    case SETVDD:

    // format: 0xA0 <CCPL><CCPH><VDDLim>

    // response: -

    case SETVPP:

    // format: 0xA1 <CCPR2L><VPPADC><VPPLim>

    // response: -

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    break;


    case SET_VOLTAGE_CALS: // ignore

    // format: 0xB0 <adc_calfactorL><adc_calfactorH><vdd_offset><calfactor>

    // response: -

    usb_idx+=5;

    break;


    case DOWNLOAD_SCRIPT: // Store a script in the Script Buffer

    // format: 0xA4 <Script#><ScriptLengthN><Script1><Script2>....<ScriptN>

    // response: -

    WrByteExtEE(inbuffer[usb_idx++]); // A4

    WrByteExtEE(inbuffer[usb_idx++]); // Script#

    temp = inbuffer[usb_idx++]; // script length

    WrByteExtEE(temp);

    do

    {

    WrByteExtEE(inbuffer[usb_idx++]);

    temp--;

    } while (temp > 0);

    break;


    case EXECUTE_SCRIPT: // immediately executes the included script

    // format: 0xA6 <ScriptLengthN><Script1><Script2>....<ScriptN>

    // response: -

    WrByteExtEE(inbuffer[usb_idx++]); // A6

    temp = inbuffer[usb_idx++]; // ScriptLengthN

    WrByteExtEE(temp);

    do

    {

    WrByteExtEE(inbuffer[usb_idx++]);

    temp--;

    } while (temp > 0);

    break;





    case DOWNLOAD_DATA: // add data to download buffer

    // format: 0xA8 <datalength><data1><data2>....<dataN>

    // response: -

    WrByteExtEE(inbuffer[usb_idx++]); // A8

    temp = inbuffer[usb_idx++]; // datalength

    WrByteExtEE(temp);

    do

    {

    WrByteExtEE(inbuffer[usb_idx++]);

    temp--;

    } while (temp > 0);

    break;


    case CLR_DOWNLOAD_BUFFER: // empties the download buffer

    // format: 0xA7

    // response: -

    case CLR_UPLOAD_BUFFER: // empties the upload buffer

    // format: 0xA9

    // response: -

    case UPLOAD_DATA: // reads data from upload buffer

    // format: 0xAA

    // response: <DataLengthN><data1><data2>....<dataN>

    case CLR_SCRIPT_BUFFER:

    // format: 0xAB

    // response: -

    case UPLOAD_DATA_NOLEN: // reads data from upload buffer

    // format: 0xAC

    // response: <data1><data2>....<dataN>

    // META-COMMANDS--------------------------------

    case READ_BANDGAP: //

    case WRITE_CFG_BANDGAP: //

    WrByteExtEE(inbuffer[usb_idx++]);

    break;


    case READ_STATUS:

    case READ_VOLTAGES: //ignore

    case RESET: // ignore

    // format: 0xAE

    // response: -

    case SCRIPT_BUFFER_CHKSM: // ignore

    usb_idx++;

    break;


    case RUN_SCRIPT: // run a script from the script buffer

    // format: 0xA5 <Script#><iterations>

    // response: -

    // META-COMMANDS--------------------------------

    case START_CHECKSUM: // clear checksum

    case VERIFY_CHECKSUM:

    case CHANGE_CHKSM_FRMT:

    case READ_OSCCAL: // read OSCCAL value

    case WRITE_OSCCAL: // write OSCCAL value

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    break;

    // META-COMMAND---------------------------------

    case CHECK_DEVICE_ID:

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    WrByteExtEE(inbuffer[usb_idx++]);

    break;


    default: // extraneous command

    usb_idx++; // ignore

    } // end switch

    } while (usb_idx < 64); // end DO

    }


    /******************************************************************************

    * Function: void PK2GoExecute(void)

    *

    * Overview: Processes commands and data from external EEPROM

    *

    * PreCondition:

    *

    * Input:

    *

    * Output: None

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void PK2GoExecute(void)

    {

    unsigned char NextCmd;

    unsigned char temp;


    PK2GoInit();

    eebuffer_idx = 64; // force a read on first access


    do

    {

    NextCmd = RdByteExtEE();


    switch(NextCmd)

    {


    // META-COMMANDS--------------------------------

    case READ_OSCCAL: // read OSCCAL value

    temp = RdByteExtEE();

    ReadOSCCAL(temp, RdByteExtEE());

    break;


    case WRITE_OSCCAL: // write OSCCAL value

    temp = RdByteExtEE();

    WriteOSCCAL(temp, RdByteExtEE());

    break;


    case START_CHECKSUM:

    checksum_l = 0;

    checksum_h = 0;

    case CHANGE_CHKSM_FRMT:

    checksum_bl_mr = RdByteExtEE();

    RdByteExtEE(); // 2nd arg is not used

    break;


    case VERIFY_CHECKSUM: // sets checksum to 0 if match.

    checksum_l = ~checksum_l;

    checksum_h = ~checksum_h;

    checksum_l ^= RdByteExtEE();

    checksum_h ^= RdByteExtEE();

    break;


    case CHECK_DEVICE_ID:

    asm_temp5 = RdByteExtEE(); // mask_l

    asm_temp6 = RdByteExtEE(); // mask_h

    asm_temp7 = RdByteExtEE(); // val_l

    asm_temp8 = RdByteExtEE(); // valu_h

    if (!CheckDeviceID())

    {

    pk2go_error_code = 1; // device ID error.

    NextCmd = END_OF_BUFFER; // Stop processing.

    }

    break;


    case READ_BANDGAP:

    ReadBandGap();

    break;


    case WRITE_CFG_BANDGAP:

    WriteCfgBandGap();

    break;


    // NORMAL COMMANDS--------------------------------

    case NO_OPERATION: // Do nothing

    // format: 0x5A

    break;


    case SETVDD:

    // format: 0xA0 <CCPL><CCPH><VDDLim>

    // CCPH:CCPL = ((Vdd * 32) + 10.5) << 6 where Vdd is desired voltage

    // VDDLim = (Vfault / 5) * 255 where Vdd < VFault is error

    // response: -

    temp = RdByteExtEE();

    CalAndSetCCP1(RdByteExtEE(), temp);

    VddVppLevels.VddThreshold = CalThresholdByte(RdByteExtEE()); // Set error threshold

    break;


    case SETVPP:

    // format: 0xA1 <CCPR2L><VPPADC><VPPLim>

    // CCPR2L = duty cycle. Generally = 0x40

    // VPPADC = Vpp * 18.61 where Vpp is desired voltage.

    // VPPlim = Vfault * 18.61 where Vdd < VFault is error

    // response: -

    Vpp_PWM.CCPRSetPoint = RdByteExtEE();

    Vpp_PWM.UppperLimit = CalThresholdByte(RdByteExtEE())+1;

    Vpp_PWM.LowerLimit = Vpp_PWM.UppperLimit - 2;

    VddVppLevels.VppThreshold = CalThresholdByte(RdByteExtEE());

    break;


    case DOWNLOAD_SCRIPT: // Store a script in the Script Buffer

    // format: 0xA4 <Script#><ScriptLengthN><Script1><Script2>....<ScriptN>

    // response: -

    PK2GoStoreScriptInBuffer();

    break;


    case RUN_SCRIPT: // run a script from the script buffer

    // format: 0xA5 <Script#><iterations>

    // response: -

    temp = RdByteExtEE();

    RunScript(temp, RdByteExtEE());

    break;


    case EXECUTE_SCRIPT: // immediately executes the included script

    // format: 0xA6 <ScriptLengthN><Script1><Script2>....<ScriptN>

    // response: -

    temp = RdByteExtEE(); // length

    CopyScriptToInbuffer(temp);

    ScriptEngine(&inbuffer[0], temp);

    break;


    case CLR_DOWNLOAD_BUFFER: // empties the download buffer

    // format: 0xA7

    // response: -

    ClearDownloadBuffer();

    break;


    case DOWNLOAD_DATA: // add data to download buffer

    // format: 0xA8 <datalength><data1><data2>....<dataN>

    // response: -

    PK2GoWriteDownloadDataBuffer();

    break;


    case CLR_UPLOAD_BUFFER: // empties the upload buffer

    // format: 0xA9

    // response: -

    ClearUploadBuffer();

    break;


    case UPLOAD_DATA_NOLEN: // reads data from upload buffer

    case UPLOAD_DATA: // reads data from upload buffer

    // format: 0xAA

    // response: <DataLengthN><data1><data2>....<dataN>

    CalcUploadChecksum();

    break;


    case CLR_SCRIPT_BUFFER:

    // format: 0xAB

    // response: -

    ClearScriptTable();

    break;


    default: // End of Buffer or unrecognized command

    NextCmd = END_OF_BUFFER; // Stop processing.

    } // end switch

    } while(NextCmd != END_OF_BUFFER);


    }


    /******************************************************************************

    * Function: char CheckDeviceID(void)

    *

    * Overview: Reads and checks the target Device ID

    *

    * PreCondition: None

    *

    * Input: asm_temp2/1 = deviceID mask

    * asm_temp4/3 = deviceID value

    *

    * Output: returns 1 if device ID matches, 0 if not

    *

    * Side Effects:

    *

    * Note: None

    *****************************************************************************/

    char CheckDeviceID(void)

    {

    // clear upload buffer

    ClearUploadBuffer();

    RunScript(0, 1); // program entry

    RunScript(2, 1); // Read Device ID

    RunScript(1, 1); // program exit

    // apply mask

    asm_temp5 &= uc_upload_buffer[uploadbuf_mgmt.read_index++];

    asm_temp6 &= uc_upload_buffer[uploadbuf_mgmt.read_index++];

    // reclear upload buffer

    ClearUploadBuffer();

    // check value

    if ((asm_temp5 == asm_temp7) && (asm_temp6 == asm_temp8))

    {

    return 1; // pass

    }

    return 0; //fail

    }


    /******************************************************************************

    * Function: void CalcUploadChecksum(void)

    *

    * Overview: Adds the bytes in the Upload buffer to checksum_h\l

    *

    * PreCondition: None

    *

    * Input: checksum_h\l

    *

    * Output: checksum_h\l

    *

    * Side Effects: Empties Upload buffer

    *

    * Note: None

    *****************************************************************************/

    void CalcUploadChecksum(void)

    {

    unsigned int *checksum = &checksum_l;

    unsigned char i, temp;


    for (i = 0; i < uploadbuf_mgmt.used_bytes; i++)

    {

    temp = uc_upload_buffer[uploadbuf_mgmt.read_index++];

    if (checksum_bl_mr)

    { // clear start/stop bits.

    if (i & 0x1)

    {

    if (checksum_bl_mr & 0x01)

    temp &= 0x7F; // flash

    else

    temp &= 0x01; // eeprom

    }

    else

    temp &= 0xFE;

    }

    *checksum += temp;

    }


    ClearUploadBuffer();


    }


    /******************************************************************************

    * Function: void ReadBandGap(void)

    *

    * Overview: Reads Badgap from target device config word

    *

    * PreCondition: None

    *

    * Input: None

    *

    * Output: bandgap_save_h (masked with 0x30 unshifted)

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void ReadBandGap(void)

    {

    // clear upload buffer

    ClearUploadBuffer();

    RunScript(0, 1); // program entry

    RunScript(13, 1); // CONFIG_RD Read

    RunScript(1, 1); // program exit

    bandgap_save_h = uc_upload_buffer[1] & 0x60;

    // reclear upload buffer

    ClearUploadBuffer();

    }


    /******************************************************************************

    * Function: void WriteCfgBandGap(void)

    *

    * Overview: Writes config word (expected in DL buffer)

    * with bandgap_save_h OR'd in. Expects

    * that prog entry / exit are in DL stream.

    *

    * PreCondition: config word in buffer must have all BG bits set to 0

    *

    * Input: bandgap_save_h

    *

    * Output: None

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void WriteCfgBandGap(void)

    {

    uc_download_buffer[1] |= bandgap_save_h;

    RunScript(15, 1); // CONFIG_WR

    }


    /******************************************************************************

    * Function: void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h)

    *

    * Overview: Reads OSCCAL from target device

    *

    * PreCondition: None

    *

    * Input: addr_l, addr_h = OSCCAL address

    *

    * Output: osccal_save_x

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void ReadOSCCAL(unsigned char addr_l, unsigned char addr_h)

    {

    // clear download buffer

    ClearDownloadBuffer();

    // clear upload buffer

    ClearUploadBuffer();

    // Put address in DL buffer

    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_l;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_h;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = 0;

    downloadbuf_mgmt.used_bytes += 3;

    RunScript(0, 1); // program entry

    RunScript(20, 1); // OSCCAL Read

    RunScript(1, 1); // program exit

    osccal_save_l = uc_upload_buffer[uploadbuf_mgmt.read_index++];

    osccal_save_h = uc_upload_buffer[uploadbuf_mgmt.read_index++];

    // reclear upload buffer

    ClearUploadBuffer();

    }


    /******************************************************************************

    * Function: void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h)

    *

    * Overview: Writes saved OSCCAL from target device

    *

    * PreCondition: None

    *

    * Input: addr_l, addr_h = OSCCAL address

    *

    * Output:

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void WriteOSCCAL(unsigned char addr_l, unsigned char addr_h)

    {

    // clear download buffer

    ClearDownloadBuffer();

    // clear upload buffer

    ClearUploadBuffer();

    // Put address & osccal in DL buffer

    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_l;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = addr_h;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = 0;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = osccal_save_l;

    uc_download_buffer[downloadbuf_mgmt.write_index++] = osccal_save_h;

    downloadbuf_mgmt.used_bytes += 5;

    RunScript(0, 1); // program entry

    RunScript(21, 1); // OSCCAL write

    RunScript(1, 1); // program exit

    }


    /******************************************************************************

    * Function: void PK2GoStoreScriptInBuffer(void)

    *

    * Overview: Stores the script from eebuffer into Script Buffer & updates

    * the Script Table.

    * Prior script at the given script # is deleted and all following

    * scripts are moved up. New script is appended at end.

    *

    * PreCondition: None

    *

    * Input:

    *

    * Output: uc_script_buffer[] - updated

    * ScriptTable[] - updated

    * Pk2Status.ScriptBufOvrFlow - set if script length > remaining buffer

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void PK2GoStoreScriptInBuffer(void)

    {

    int i;

    int LengthOfAllScripts;

    int Temp_1, Temp_2, Length;


    Temp_2 = RdByteExtEE(); // Script# of new script

    Temp_1 = RdByteExtEE(); // Length of new script

    Length = Temp_1;


    // First, make sure script length is valid

    if (Temp_1 > SCRIPT_MAXLEN)

    {

    Pk2Status.ScriptBufOvrFlow = 1; // set error - script longer than max allowed

    return;

    }


    // calculate length of all scripts.

    LengthOfAllScripts = 0;

    for (i=0; i < SCRIPT_ENTRIES; i++)

    {

    LengthOfAllScripts += ScriptTable[i].Length;

    }

    LengthOfAllScripts -= ScriptTable[Temp_2].Length; // don't count length of script being replaced

    if (Temp_1 > (SCRIPTBUFSPACE-LengthOfAllScripts)) // if there isn't enough room

    {

    Pk2Status.ScriptBufOvrFlow = 1; // set error - not enough room in script buffer

    return;

    }


    // Next, make sure script# is valid

    if (Temp_2 > (SCRIPT_ENTRIES-1)) // 0-31 valid

    {

    Pk2Status.ScriptBufOvrFlow = 1; // set error - script# invalid

    return;

    }



    if (ScriptTable[Temp_2].Length != 0) // If a script exists in that location

    {

    // Move space created by deleting existing script to end of buffer.

    Temp_1 = (SCRIPTBUFSPACE - ScriptTable[Temp_2].Length) - 1; // last copy location.

    for (i=ScriptTable[Temp_2].StartIndex; i < Temp_1; i++)

    {

    *(uc_ScriptBuf_ptr + i) = *(uc_ScriptBuf_ptr + ScriptTable[Temp_2].Length + i);

    }

    // update script table entries

    for (i=0; i < SCRIPT_ENTRIES; i++)

    {

    if (ScriptTable[i].StartIndex > ScriptTable[Temp_2].StartIndex) // if script is in moved section

    {

    ScriptTable[i].StartIndex -= ScriptTable[Temp_2].Length; // adjust by amount moved

    }

    }

    }


    // Store new script at end of buffer

    ScriptTable[Temp_2].Length = Length; // update Script Table Entry with new length.

    ScriptTable[Temp_2].StartIndex = LengthOfAllScripts; // update entry with new index at end of buffer.

    for (i = 0; i < ScriptTable[Temp_2].Length; i++)

    {

    *(uc_ScriptBuf_ptr + LengthOfAllScripts + i) = RdByteExtEE();

    }


    } // end void StoreScriptInBuffer


    /******************************************************************************

    * Function: void CopyScriptToInbuffer(unsigned char len)

    *

    * Overview: Stores the script from eebuffer into the inbuffer

    *

    * PreCondition: None

    *

    * Input:

    *

    * Output: inbuffer = script

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void CopyScriptToInbuffer(unsigned char len)

    {

    unsigned char i;


    for (i = 0; i < len; i++)

    {

    inbuffer[i]= RdByteExtEE();

    }

    }


    /******************************************************************************

    * Function: void PK2GoWriteDownloadDataBuffer(void)

    *

    * Overview: Writes a given # of bytes into the data download buffer.

    *

    * PreCondition: None

    *

    * Input:

    *

    * Output: uc_download_buffer[] - updated with new data

    * downloadbuf_mgmt.write_index - incremented by length of data stored.

    * downloadbuf_mgmt.used_bytes - incremented by length of data stored.

    * Pk2Status.DownloadOvrFlow - set if data length > remaining buffer

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void PK2GoWriteDownloadDataBuffer(void)

    {

    unsigned int i, numbytes;


    numbytes = RdByteExtEE() & 0xFF; // i= # bytes data (length)


    if ((numbytes + downloadbuf_mgmt.used_bytes) > DOWNLOAD_SIZE) // not enough room for data

    {

    Pk2Status.DownloadOvrFlow = 1;

    return;

    }


    for (i = 0; i < numbytes; i++)

    {

    uc_download_buffer[downloadbuf_mgmt.write_index++] = RdByteExtEE();

    if (downloadbuf_mgmt.write_index >= DOWNLOAD_SIZE) // handle index wrap

    {

    downloadbuf_mgmt.write_index = 0;

    }

    downloadbuf_mgmt.used_bytes++; // used another byte.

    }

    } // end void PK2GoWriteDownloadDataBuffer(void)


    /******************************************************************************

    * Function: void Pk2GoErrorBlink(unsigned char blinksX2)

    *

    * Overview: Blinks the BUSY LED for the given # of blinks until

    * the pushbutton is pressed

    *

    * PreCondition: None

    *

    * Input: blinksX2 = twice the # of blinks in sequence

    *

    * Output:

    *

    * Side Effects: None

    *

    * Note: None

    *****************************************************************************/

    void Pk2GoErrorBlink(unsigned char blinksX2)

    {

    char i = 0;


    while(PROG_SWITCH_pin)

    {

    if (i <= blinksX2)

    BUSY_LED = i++ & 0x1;

    else

    i = 0;

    Delay10KTCYx(240); // 200ms

    }

    }





    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 17 Mart 2024; 18:24:21 >
    < Bu ileti mini sürüm kullanılarak atıldı >




  • Spi desteği olan hangi EE chipi kullanmayı planlıyorsunuz?


    Genelde Spi flash larda içine veri yazmadan önce ilgili hücrenin 0xFF (bu projede tüm chipin içeriğinin) olması gerekir. Spi flaslarda silme işlemi, allchip, sector ve block bazlı yapılır. I2C lerde direk üzerine veri yazılabiliyor bu durumu göz önünde bulundurun. Seçtiğiniz spi chip üzerine veri yazmayı destekliyorsa yukarıdaki uyarıyı göz ardı edebilirsiniz.


    Siz konuya çok daha fazla kafa yordunuz ama kodunuzdaki aşağıdaki kısım biraz garip geldi. Adres parçalama işlemine bir mana veremedim. Farklı bir mantığı varsa açıklarsanız iyi olur.


    unsigned int ext_ee_addr;


    C18 derleyicide unsigned int 16 bitlik yani 2 byte yer kaplar.

    Düşük, orta, yüksek byte seçimlerinde 8 bit kaydırmanız gerekmez mi?

    Aynı zamanda ext_ee_addr tipinin 3 byte veya daha uzun bir değişken olarak tanımlanması gerekmez mi?


    Ör: unsigned shot long (24bit) veya unsigned long(32bit) gibi.




      //EE adresinin düşük byte'ını oluştur. Generate low byte of EE addres

    if(address == 0)

    {

      add = (ext_ee_addr << 6) & 0xFF; //<<--- düşük için niye sola 6 bit

    add = ext_ee_addr & 0xFF; // normalde bu şekilde düşük byte alınır

    }

      //EE adresinin orta byte'ını oluştur. Generate middle byte of EE addres

    if(address == 1)

    {

      add = (ext_ee_addr >> 2) & 0xFF; // <<--- orta için niye 2 bit sağa

    add = (ext_ee_addr>>8) & 0xFF; // normalde bu şekilde yüksek byte alınır.

    }

      //EE adresinin yüksek byte'ını oluştur. Generate high byte of EE addres

    if(address == 2)

    {

      add = (ext_ee_addr >> 10) & 0xFF; // <-- yüksek için tekrar sağa 10 bit kaydırıldı

    // ext_ee_addr 2 byte olduğu için 3. kez sağa kaydırma yapmanın bir anlamı yok

    }

    return add;





  • rafet32 kullanıcısına yanıt
    ext_ee_addr değişkeni 64'ün katlarıdır. Açıklama kısmında multiples of 64 diye yazılmış.
    ext_ee_addr 0 = byte 0 - 63,
    ext_ee_addr 1 = byte 64 - 127
    ext_ee_addr 2 = byte 128 - 191
    ...
    ext_ee_addr 65535 byte 4.194.240 - 4.194.304

    SPI flash kullanacağım. SPI flashlar geleneksel 25xx SPI EEPROM'lardan farklı olarak 24bit adresleme ile çalışır. Dolayısı ile adres verisini 24 bit olarak göndermek gerekir.
    Programmer to Go'da sadece PC'den PICkit'e veri kaydederken EEPROM'a veri yazılır. Dolayısı ile çipin önceden silinmiş olup olmadığını bir değişken ve if koşulu ile kontrol edip sadece yazma fonksiyonu ilk çalıştığında silme işlemini yapmak bana daha mantıklı geldi. Yazma fonksiyonu ilk çalışmada çipi silecek ve çipi silinmiş olarak işaretleyecek. if(!cleaned) ifadesi cleaned ==0 ise silme rutinini çalıştır: if'ten çıktıktan hemen sonra cleaned ifadesi 1 olarak değiştirilecek. Yazma fonksiyonu tekrar çağrıldığında cleaned'e bakacak. 1 gördüğünde silme işlemini atlayıp doğrudan yazmaya geçecek. Cleaned değişkenini fonksiyonun dışında tanımladım, yazma fonksiyonundan çıktıktan sonra hafızadan silinmeyecek.


    ext_ee_addr'ı 64 ile çarpar byte adresi haline getiririz. 64, 2 üzeri 6'dır.
    Yani 6 bit sola kaydırma yaparız.

    "ext_ee_addr << 6"

    Low byte için doğrudan 6 bit sola kaydırıp ilk byte'ı maskelemek yeterli.
    "(ext_ee_addr << 6) & 0xFF"

    Medium byte için 6 bit sola kaydırdığımız değeri 8 bit sağa kaydırıp medium byte'ın en başa gelmesini sağlarız. Ardından FF ile maskeleyerek alırız. İşte 6 bit sola 8 bit sağa kaydırınca sonuç olarak 2 bit sağa kaydırmış oluyoruz.
    "((ext_ee_addr << 6) >> 8) & 0xFF"

    High byte için 6 bit sola kaydırdığımız değeri iki sefer 8 bit sağa kaydırıp high byte'ın en başa gelmesini sağlarız. Ardından FF ile maskeleyerek alırız. İşte 6 bit sola 16 bit sağa kaydırınca sonuç olarak 10 bit sağa kaydırmış oluyoruz.
    "(((ext_ee_addr << 6) >> 8) >> 8) & 0xFF"



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 18 Mart 2024; 13:39:13 >
    < Bu ileti mini sürüm kullanılarak atıldı >




  • Anlaşılan gerçek adresi bulmak için 64 ile çarpma işlemi için böyle bir yapı kurulmuş. Benim önerim 18f2550 de donanımsal çarpma desteği var. Bundan faydalanıp


    adres = ext_ee_addr * 64; // Eski mesaj yanlış:tek bir clock cycle Düzeltme doğrusu:28 clock cycle (değişken tipi uint16 olduğu için) de bu işlem gerçekleşir.


    Şeklinde bir kullanım işleri daha kolaylaştırır.


    Diğer bir öneri ise: Her 64 byte lik paket yazmada

    ext_ee_addr++;


    bir artırılıyor.


    Bunun yerine ext_ee_addr +=64;

    Şeklinde yaparsanız sonraki gerçek adres zaten elinizin altında olur. Çarpma veya bit maniplasyonu gibi dertlerden kurtulursunuz.


    Bu sayede yukarıdaki mesajda belirttiğim gibi her seferininde sağa 8 in katları bit kaydırarak adresin byte verilerine erişebilirsiniz.

    Bit kaydırma yerine pointer kullanımınıda düşünebilirsiniz. Bu proje kullanımında performans konusunda ve kod okunurluğu konusunda bir farkı olmaz ama, genel alışkanlık ve kullanım tercihi olarak şöylede yapabilirsiniz.


    uint32 adres;

    uint8 *p8; //pointer tanımlama

    uint8 adr;


    p8 = (uint8*)&adres; // pointer adresin lsb byte i işaret ediyor.


    adr = *p8; // lsb ilk byte

    p8++; // pointeri bir artır

    adr = *p8; // 2. byte

    p8++; // sonraki byte

    adr = *p8; // 3. byte

    p8++; // sonraki byte

    adr = *p8; // 4. byte




    < Bu mesaj bu kişi tarafından değiştirildi rafet32 -- 19 Mart 2024; 9:51:52 >




  • rafet32 kullanıcısına yanıt
    Ama hafıza işte, bunu yapmak için 16 bitlik ext_ee_addr değişkenini 32 bite çıkarmam lazım. ext_ee_addr değişkeni global, hafızada sürekli yer işgal ediyor. Zaten hafıza öyle bir ayarlanmış ki bir byte bile fazladan kullandın mı hafıza sınırı aşıldı diyen link step hatasına düşüyor. Dolayısı ile hafızayı idareli kullanmam lazım.

    Ama AddExtEE içerisine yerel değişken atayıp ext_ee_addr*64'ü buraya atmak düşünülebilir.

    < Bu ileti mini sürüm kullanılarak atıldı >
  • Hafıza (RAM) kapasitesi ile ilgili sorun / yetmeme durumu varsa pointer ile aynı hafıza bölgesini ortak kullanabilirsiniz. Bu sayede bit maniplasyonu ve kaydırma gibi işler için local değişken tanımlamanıza bile gerek kalmaz. Yukarıdaki örnekde


    uint8 adr;


    tanımlamasını sizin kod uyumunuza benzemesi ve daha rahat anlatmak içindi. Yoksa *p8 zaten ilgili hafıza (ram) adresini bir byte olarak işaret ediyor. Doğrudan *p8 şeklindede kullanılabilir.


    MPlab ide sini kullanmadığım için deneme yapma imkanım yok ama ramde 2 byte alacak kadar yer vardır herhalde 2048 byte ram çokda az değil PICkit2 Programmer to go hafıza çiplerini SPI flash yapma 

  • rafet32 kullanıcısına yanıt
    Şu pointer olayına bir bakayım. Teşekkürler.
    İnterneti kurcalarken bu sayfayı buldum. Çok işime yarayacak bilgiler var. Hem de Mplab (x olmayan düz mplab) üzerinden anlatılmış.

    www.electronicwings.com
    PIC18F4550 SPI | PIC Controllers
    https://www.electronicwings.com/pic/pic18f4550-spi


    Güncel derleyiciler bu tip çevresel okuma yazma işlemleri için dahili fonksiyonlara sahip. SPI_write() diyorsun gönderiyor, SPI_read() oku diyorsun alıyor.
    Bayrağıyla, tampon taştı taşmadı vs. ile uğraşmıyorsun. Bu sayede gereksiz teferruatlarla uğraşmadan asıl işine odaklanabiliyorsun.

    Pickit2 kodlarının yazılmış olduğu Mplab ide derleyicisi bunlardan yoksun. Mecbur her şeyi elle yapıyoruz. Mesela Pickit3'ün yazılmış olduğu mplab X SPI ve İ2C için dahili fonksiyonlara sahip. Bu nedenle kodları daha sade.



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 18 Mart 2024; 22:15:18 >
    < Bu ileti mini sürüm kullanılarak atıldı >




  • Pickit3 de U3 ve U4 hafıza chipleri U3=i2c U4=spi modunda çalışıyor. Belki fikir verebilir. Benim emektarlar, Pickit2 daha fazla kullanılmış PICkit2 Programmer to go hafıza çiplerini SPI flash yapma 



    PICkit2 Programmer to go hafıza çiplerini SPI flash yapma
  • rafet32 kullanıcısına yanıt
    Hiç PICkit3'üm olmadı. 😢

    PICkit3 kodlarına da bakmıştım. Mplab X ile yazmışlar. Hafıza iletişimi için MplabX'in dahili SPİ fonksiyonlarını kullanmışlar.
    Benim işime yarayabilecek düşük seviyeli bir SPI haberleşme kodu mevcut değil.

    quote:

    Benim önerim 18f2550 de donanımsal çarpma desteği var.

    PIC18'lerde olup, PIC16'larda olmayan; namını çok duyduğum 8x8 Hardware multiplier diye bir özellik var. Ondan mı bahsediyorsunuz?



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 18 Mart 2024; 23:33:9 >
    < Bu ileti mini sürüm kullanılarak atıldı >
  • Alıntı

    metni:
    Hiç PICkit3'üm olmadı.


    Çok birşey kaybetmiş değilsiniz aslında. Alışkanlıkdanmıdır yazılımının kolay ve hızlı kullanılmasındanmıdır pickit2 yi daha çok tercih ediyorum. Diğeri pickit2 nin desteklemediği (device list dosyasını düzenleyerek eklemek bir yöntem ama her zaman için optimum yöntem olmuyor) bazı mcular olduğunda arada bir kullanıyorum.



    Evet hardware multiplier den bahsediyoruz ama yukarıdaki mesajda hatalı ifade ettim (o mesajı yazarken 32bit arm mimarisi gibi düşündüm bir an için). 1 cycle de çarpma işlemini 8 bitlik işaretsiz sayılarda yapabiliyor. Aşağıdaki tablo çarpma işleminin donanımsal olup olmamasının ROM ve cpu zamanı kullanımı açısından karşılaştırmasını veriyor. Tablo 18f2550 nin pdf inden alındı.


    Tablonun ilk satırı için unsigned 8 bit işlemlerde 26byte (13 word) daha az ROM kullanıyor ve 69 kat daha hızlı işlemi sonuçlandırıyor.

    Diğer veri tipleri için tabloya aynı mantıkla bakabilirsiniz.



    PICkit2 Programmer to go hafıza çiplerini SPI flash yapma




  • rafet32 kullanıcısına yanıt
    Ama medium ve high byte'ların hesabında sağa bit kaydırma yapılıyor. Bunlar matematiksel olarak 2^8 ve 2^16'ya bölme işlemine tekabül ediyor. Anladığım kadarıyla hardware multiplier sadece integer'ları çarparken işe yarıyor. Bölme işleminde kullanamıyoruz.



    < Bu mesaj bu kişi tarafından değiştirildi ipli jeton -- 19 Mart 2024; 15:33:28 >
    < Bu ileti mini sürüm kullanılarak atıldı >
  • Mcu nun komut setinde sola veya sağa bit kaydırma (Rotate Left ve Rotate Right) komutları var. Fakat bu mcu 8 bitlik olduğu için, buradaki 1 cpu zamanı 8 bitlik değişkenler üzerinde işlem yapıldığında geçerli. Sizin örnekdeki eeprom adresini tuttuğunuz değişken gibi 16 bitlik veya 32 bitlik bir değişkenin bitlerini sağa veya sola kaydırmak istediğinizde bu daha fazla cpu zamanına mal olacaktır çünkü aynı anda sadece 8 bit üzerinde işlem yapma kapasitesine sahip. Bu durumda adres değişkeni içerisindeki byte lara erişmek için pointer kullanmak daha hızlı bir yöntem olacaktır.


    8 e veya 16 ya bölme işlemlerinde derleyicinin Rotate komut setlerini kullanması beklenir. (Ondalık / floating point çarpma ve bölme işlemleri farklı bir konu)


    Birde hız herşey demek değildir, yerine göre bir işlemin 10us de bitmesi ile 80us de bitmesi çokda önemli değildir, fakat aradaki farkları bilmek ve gerekli olduğu zamanlarda doğru yöntemi tercih edebilmek önemli / avantajlı hale gelecektir.



    PICkit2 Programmer to go hafıza çiplerini SPI flash yapma




    Not: Doğrudan assembler yazmıyorsanız, araya kullandığınız compiler ve onun ayarları, optimizasyon yetenekleri devreye girecektir. Çıkan makine kodu ve performansı değişecektir. Assemblerde yazdığınız kodlar gördüğünüz şekilde işlenecektir. İyi yazdıysanız iyi, kötü yazdıysanız kötü performansda çalışacaktır.


    Derleyici farkına örnek olaması açısından, geçmişte elimdeki mcunun bir pininden aşağıdaki gibi basit bir kod ile kaç Hz sinyal alabilirim diye test yapmıştım.


    pseudo code

    while(1)

    {

    pin1 = H;

    pin1 = L;

    }


    Aynı kod aynı mcu, aynı configrasyonda çalıştırıldığında

    Derleyici 1 : 1.2 Mhz

    Derleyici 2 : 6.0 Mhz


    C ile kodlama yapıyorsanız kullandığınız derleyicinin kabiliyetlerine ve optimizasyon seçimlerine göz atmanızda fayda var.





  • Mesajınıza daha sonra ilave ettiğiniz kısmı sonradan gördüm. SPI modülünü aktif ettiğinizde zaten onun bağlı olduğu IO larda uygun şekilde konfigüre edilir. TRIS yapmaya gerek yok. TRIS kullanmanın gereksiz cpu zamanı ve romda yer kaplaması haricinde bir zararıda yok :)


    Edit2: C derleyicilerde bu işlem arka planda yapılır, yukarıdaki açıklama buna göre yapıldı ama assembler kullanıyorsanız pinleri uygun şekilde input veya output olarak ayarlamanız gerekir.


    Edit: Mesajı sonradan düzenlediğiniz için yukarıdaki cevap askıda kaldı.




    < Bu mesaj bu kişi tarafından değiştirildi rafet32 -- 19 Mart 2024; 15:45:15 >
  • 
Sayfa: 123
Sayfaya Git
Git
sonraki
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.