problems using atmega644pv jtag pins as gpio
Section 8.10.7 in the datasheet lists the following ways to disable JTAG


Disable the OCDEN Fuse. 
Disable the JTAGEN Fuse. 
Write one to the JTD bit in MCUCR.


You say you have disabled JTAG from the fuses but just in case, can you add the following at the start of main (or setup)

MCUCR |=(1&lt;&lt;JTD);
MCUCR |=(1&lt;&lt;JTD); 


The JTD bit needs to be written twice :


  In order to avoid unintentional disabling or enabling of the JTAG interface, a timed sequence must be followed when changing this bit: The application software must write this bit to the desired value twice within four cycles to change its value. 




I noticed that you have already included the following in setup()

MCUCR |= (1&lt;&lt;JTD);


but a single write will not have any effect as I explained above



Adding to what Ignacio Vazquez-Abrams wrote in the comments, you may run into trouble with the read-modify-write operation as opposed to a write only operation.

(using avrgcc)  

READ/MODIFY/WRITE

with Os,O3,O2 optimization level the read/modify/write you get a code which is barely within the 4 cycle limit but will work:

    MCUCR |= (1 &lt;&lt; JTD);
  88:   85 b7           in  r24, 0x35   ; 53
  8a:   80 68           ori r24, 0x80   ; 128
  8c:   85 bf           out 0x35, r24   ; 53
    MCUCR |= (1 &lt;&lt; JTD);
  8e:   85 b7           in  r24, 0x35   ; 53
  90:   80 68           ori r24, 0x80   ; 128
  92:   85 bf           out 0x35, r24   ; 53


With O1 optimization level you get a code which will not work (7 cycle between writes):

    MCUCR |= (1 &lt;&lt; JTD);
  94:   e5 e5           ldi r30, 0x55   ; 85
  96:   f0 e0           ldi r31, 0x00   ; 0
  98:   80 81           ld  r24, Z
  9a:   80 68           ori r24, 0x80   ; 128
  9c:   80 83           st  Z, r24
    MCUCR |= (1 &lt;&lt; JTD);
  9e:   80 81           ld  r24, Z
  a0:   80 68           ori r24, 0x80   ; 128
  a2:   80 83           st  Z, r24
  a4:   ff cf           rjmp    .-2         ; 0xa4 &lt;main+0x10&gt;


With O0 (optimization off) you get a code which is way off from the 4 cycle limit:

    MCUCR |= (1 &lt;&lt; JTD);
  90:   a5 e5           ldi r26, 0x55   ; 85
  92:   b0 e0           ldi r27, 0x00   ; 0
  94:   e5 e5           ldi r30, 0x55   ; 85
  96:   f0 e0           ldi r31, 0x00   ; 0
  98:   80 81           ld  r24, Z
  9a:   80 68           ori r24, 0x80   ; 128
  9c:   8c 93           st  X, r24
    MCUCR |= (1 &lt;&lt; JTD);
  9e:   a5 e5           ldi r26, 0x55   ; 85
  a0:   b0 e0           ldi r27, 0x00   ; 0
  a2:   e5 e5           ldi r30, 0x55   ; 85
  a4:   f0 e0           ldi r31, 0x00   ; 0
  a6:   80 81           ld  r24, Z
  a8:   80 68           ori r24, 0x80   ; 128
  aa:   8c 93           st  X, r24
  ac:   ff cf           rjmp    .-2         ; 0xac &lt;main+0x24&gt;




WRITE

A better approach is to just use a write operation that will work fine with any optimization level (Os,O1,O2,O3) but not when you disable optimization (O0)

Using Os, O3, O2

    MCUCR = (1 &lt;&lt; JTD);
  88:   80 e8           ldi r24, 0x80   ; 128
  8a:   85 bf           out 0x35, r24   ; 53
    MCUCR = (1 &lt;&lt; JTD);
  8c:   85 bf           out 0x35, r24   ; 53


Using O1

    MCUCR = (1 &lt;&lt; JTD);
  94:   e5 e5           ldi r30, 0x55   ; 85
  96:   f0 e0           ldi r31, 0x00   ; 0
  98:   80 e8           ldi r24, 0x80   ; 128
  9a:   80 83           st  Z, r24
    MCUCR = (1 &lt;&lt; JTD);
  9c:   80 83           st  Z, r24


Using O0

  MCUCR = (1 &lt;&lt; JTD);
  9c:   e5 e5           ldi r30, 0x55   ; 85
  9e:   f0 e0           ldi r31, 0x00   ; 0
  a0:   80 e8           ldi r24, 0x80   ; 128
  a2:   80 83           st  Z, r24
    MCUCR = (1 &lt;&lt; JTD);
  a4:   e5 e5           ldi r30, 0x55   ; 85
  a6:   f0 e0           ldi r31, 0x00   ; 0
  a8:   80 e8           ldi r24, 0x80   ; 128
  aa:   80 83           st  Z, r24