I'm trying to replace 25L3206E flash memory with Arduino Nano. Datasheet: 25L3206E datasheet
Memory chip is removed from PCB and Arduino is attached in place. Device is KCodes KC601. Link to product: KC601 - Wired - Product - KCodes
Pin mapping:
Chip Select is on pin D3 and uses interrupt 1.
Clock is on pin D2 and uses interrupt 0.
Serial In is on pin D4.
Serial Out is on pin D5. (not used in this code yet)
This is hobby project. Kind of hardware hacking. I'm trying to run firmware directly from Arduino. Firmware is converted to hexadecimal array and saved in to PROGMEM. It contains over thousand lines of code, so I don't include it here.
I also use Nokia 5110, PCD8544 monochrome graphic display to debug purposes. Datasheet: https://www.sparkfun.com/datasheets/LCD/Monochrome/Nokia5110.pdf
Pin mapping:
Reset - external +5V
CE - D8
DC - D12
DIN- D11
CLK- D10
VCC- 3V
LIGHT- GND
GND - GND
Display works fine, so I don't include it's code either. Saves again 70 lines of code from flooding this post. Serial port cannot be used for debugging because of interrupts.
And worth to mention that Arduino Nano is powered with 3V through 5V output pin and 5V line is disconnected from USB cable. Works fine. KCodes KC601 uses 3V on internal data lines.
And finally the problem:
Seems that count variable is incrementing properly, but when I monitoring a command variable then after a while code is running it outputs several ones and it follows with several twos and then fours and 20 (in hexadecimal format). After that it starts again with ones. It seems that only one bit is coming through and it rolls over with cmd variable.
I don't get any error messages.
Program code:
#define SO 5
#define SI 4
volatile uint32_t addr = 0;
volatile uint32_t cmd = 0;
volatile uint16_t count = 0;
volatile uint8_t command = 0;
volatile uint8_t databyte = 0;
volatile int8_t datacount = 0;
void setup() {
pinMode(2, INPUT); // CLK
pinMode(SO, INPUT); //input - high impedance state
pinMode(SI, INPUT);
//https://sites.google.com/site/qeewiki/books/avr-guide/external-interrupts-on-the-atmega328
EICRA = 0b0101; // sense any change on the INT1 and any change on the INT0
EIMSK = 0b11; // enable INT1 and INT0 interrupt
sei(); // turn on interrupts
pinMode(13, OUTPUT); // led output
}
void loop() { // debug screen control
if (command != 0) {
asm volatile (
// calculate and print hex number to debug screen
"mov r24, %0 \n"
"swap r24 \n"
"andi r24, 0x0f \n"
"cpi r24, 0x0a \n"
"brlo lower11 \n"
"subi r24,-0x27 \n"
"lower11: \n"
"subi r24,-0x30 \n"
"call LcdChar \n"
"mov r24, %0 \n"
"andi r24, 0x0f \n"
"cpi r24, 0x0a \n"
"brlo lower22 \n"
"subi r24,-0x27 \n"
"lower22: \n"
"subi r24,-0x30 \n"
"call LcdChar \n"
"ldi r24, 0x22 \n" // delimiter character
"call LcdChar \n"
:
: "r" (command)
: "r24"
);
}
}
ISR(INT1_vect) { // Chip Select interrupt
asm volatile (
"clr %[com_] \n"
"clr %[cmd_] \n"
"clr %[ad_] \n"
"clr %[db_] \n"
"clr %[dc_] \n"
"clr %[cn_] \n"
"cbi %[portd_], %[portd5_] \n" // disable input pullup, digitalWrite(SO,LOW);
"cbi %[portd_], %[portd4_] \n" // disable input pullup, digitalWrite(SI,LOW);
"cbi %[ddrd_], %[ddd5_] \n" // pinMode(SO,INPUT); // going to high-z mode
"cbi %[ddrd_], %[ddd4_] \n" // pinMode(SI,INPUT);
"cbi %[portb_], %[portb5_] \n" // digitalWrite(13,LOW); turn off led
: [com_] "+r" (command),
[cmd_] "+r" (cmd),
[ad_] "+r" (addr),
[db_] "+r" (databyte),
[dc_] "+r" (datacount),
[cn_] "+r" (count)
: [portd_] "I" (_SFR_IO_ADDR(PORTD)), [portd5_] "I" (PORTD5),
[portd4_] "I" (PORTD4),
[ddrd_] "I" (_SFR_IO_ADDR(DDRD)), [ddd5_] "I" (DDD5), // SO direction reg
[ddd4_] "I" (DDD4), // SI direction reg
[portb_] "I" (_SFR_IO_ADDR(PORTB)), [portb5_] "I" (PORTB5) // pin 13, led
);
}
ISR(INT0_vect) { // CLK change interrupt
asm volatile (
"sbic %[pind_], %[cs_] \n" // if CS high then do not continue
"rjmp endInt \n"
"sbis %[pind_], %[clk_] \n" // CLK
"rjmp sdata \n" // if low, goto data section
"sbi %[portb_], %[led_] \n" // light up led
// loads incoming byte to cmd bit by bit
"lsl %A[cmd_] \n" // Shifts all bits one place to the left
"rol %B[cmd_] \n" //
"rol %C[cmd_] \n" // 32-bit value
"rol %D[cmd_] \n" //
"clr __tmp_reg__ \n" // clear byte
"sbic %[pind_], %[si_] \n" // Skip if bit in SI pin is cleared
"inc __tmp_reg__ \n" // set bit one
"add %A[cmd_],__tmp_reg__ \n" // add result to cmd
"adc %B[cmd_],__zero_reg__ \n" //
"adc %C[cmd_],__zero_reg__ \n" // 32-bit value
"adc %D[cmd_],__zero_reg__ \n" //
"mov r19, %A[cmd_] \n" // copy first byte
"clr __tmp_reg__ \n" // clear byte
"inc __tmp_reg__ \n" // set bit one
"add %A[cn_], __tmp_reg__ \n" // add one to counter variable
"adc %B[cn_], __zero_reg__ \n" // 16-bit value
"cpi %A[cn_], 8 \n" // compare counter variable to 8
"cpc %B[cn_], __zero_reg__ \n" // upper byte must be zero
"breq cont33 \n"
"rjmp endInt \n" // if not equal, goto end
"cont33: \n"
// select 8-bit command
"cpi r19, 0x01 \n"
"breq result \n"
"cpi r19, 0x02 \n"
"breq result \n"
"cpi r19, 0x03 \n"
"breq result \n"
"cpi r19, 0x04 \n"
"breq result \n"
"cpi r19, 0x05 \n"
"breq result \n"
"cpi r19, 0x06 \n"
"breq result \n"
"cpi r19, 0x0b \n"
"breq result \n"
"cpi r19, 0x20 \n"
"breq result \n"
"cpi r19, 0x2b \n"
"breq result \n"
"cpi r19, 0x2f \n"
"breq result \n"
"cpi r19, 0x3b \n"
"breq result \n"
"cpi r19, 0x52 \n"
"breq result \n"
"cpi r19, 0x5a \n"
"breq result \n"
"cpi r19, 0x60 \n"
"breq result \n"
"cpi r19, 0x90 \n"
"breq result \n"
"cpi r19, 0x9f \n"
"breq result \n"
"cpi r19, 0xab \n"
"breq result \n"
"cpi r19, 0xb1 \n"
"breq result \n"
"cpi r19, 0xb9 \n"
"breq result \n"
"cpi r19, 0xc1 \n"
"breq result \n"
"cpi r19, 0xc7 \n"
"breq result \n"
"cpi r19, 0xd8 \n"
"breq result \n"
"rjmp endInt \n"
"result: \n"
"mov %[com_], r19 \n" // result to command
"rjmp endInt \n"
"sdata: \n" // data section start
"endInt: \n"
: [com_] "+r" (command),
[cmd_] "+r" (cmd),
[ad_] "+r" (addr),
[db_] "+r" (databyte),
[dc_] "+r" (datacount),
[cn_] "+r" (count)
: [pind_] "I" (_SFR_IO_ADDR(PIND)), [si_] "I" (PIND4), // input SI
[cs_] "I" (PIND3), // cs
[clk_] "I" (PIND2), // clk
[ddrd_] "I" (_SFR_IO_ADDR(DDRD)), [mso_] "I" (DDD5), // pinMode SO
[portd_] "I" (_SFR_IO_ADDR(PORTD)), [so_] "I" (PORTD5), // output SO
[portb_] "I" (_SFR_IO_ADDR(PORTB)), [led_] "I" (PORTB5) // pin 13, led
: "r19", "memory"
);
}