MooshBeef

AT90CAN128 problem

May 15th, 2014
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.17 KB | None | 0 0
  1. //Chip info:
  2. AT90CAN128 @16MHz
  3.  
  4. Problem:
  5. The program jumps to memcpy in the main() randomly after the first call to renderTimeTable()
  6. placing any code in the place of memcpy that involve copying one array to the other causes the issue
  7.  
  8. //main.c
  9. #include <avr/io.h>
  10. #include <avr/interrupt.h>
  11. #include <avr/sleep.h>
  12. #include <util\delay.h>
  13. #include <string.h>
  14.  
  15. #include "pwm.h"
  16. #include "spi.h"
  17.  
  18. const int MOTOR_FOOT = 0;
  19. const int MOTOR_LEG = 1;
  20. const int MOTOR_BODY = 2;
  21.  
  22.  
  23. int main(void)
  24. {
  25. //High-bit indicates an output
  26. DDRA = 0xFF;
  27. DDRB = 0x00;
  28. DDRC = 0xFF;
  29. DDRD = 0xFF;
  30. PORTA = 0x00;
  31. PORTB = 0x00;
  32. PORTC = 0x00;
  33. PORTD = 0x00;
  34.  
  35. //Initialize counter interrupt, to execute @100kHz
  36. pwm_init();
  37. //Initialize SPI
  38. spi_init();
  39. //Enable interrupts
  40. sei();
  41.  
  42. //Build rendertable for the pwm
  43. uint8_t temp[] = {
  44. 4,50,100,150,200,250,0,0
  45. };
  46. renderTimeTable(temp);
  47.  
  48. while(1)
  49. {
  50. while(!buffer_finished){}
  51. //buffer_finished = 0;
  52. uint8_t portbuffer[8];
  53. memcpy((void*) spi_buffer, portbuffer,8);//<---PROBLEM IS HERE, it jumps to this line after the first renderTimeTable() used above
  54. //Parse buffer and write pwm
  55. renderTimeTable(portbuffer);
  56. }
  57. }
  58.  
  59. //pwm.h
  60. #ifndef HEADER_GUARD_PWM
  61. #define HEADER_GUARD_PWM
  62.  
  63. void pwm_init(void);
  64. void renderTimeTable(uint8_t[8]);
  65. volatile uint8_t timetable[200];
  66.  
  67. #endif
  68.  
  69. //pwm.c
  70. #include <avr/io.h>
  71. #include <avr/interrupt.h>
  72. #include <string.h>
  73.  
  74. #include "pwm.h"
  75.  
  76. void pwm_init(void)
  77. {
  78. //Initialize the timer for 100kHz
  79. //Set prescaler: none
  80. TCCR1B |= (1 << CS10);
  81. //Waveformgenerator mode: CTC
  82. TCCR1B |= (1 << WGM12);
  83. //Counter compare value: 160
  84. OCR1A = (uint16_t) 160;
  85. //Reset current counter
  86. TCNT1 = 0;
  87. //Enable interrupt for counter compare
  88. TIMSK1 |= (1 << OCIE1A);
  89. }
  90.  
  91. //Store timetable
  92. volatile uint8_t timetable[200];
  93. volatile uint8_t debug[8];
  94. //Render a timetable for a single port, angles has to have a length of 8!
  95. void renderTimeTable(uint8_t angles[8])
  96. {
  97. uint8_t _timetable[200];
  98. for(uint8_t time=0;time<200;time++)
  99. {
  100. _timetable[time] = 0x00;
  101. for(uint8_t i=0;i<8;i++)
  102. {
  103. _timetable[time] |= (time < angles[i])<<i;
  104. }
  105. }
  106. for(int i =0;i<200;i++)
  107. {
  108. timetable[i] = _timetable[i];
  109. }
  110. }
  111.  
  112. //Keep track of progression in PWM over 20ms -> 20000 vals;
  113. volatile uint16_t pwm_pointer = 0;
  114. //Timer interrupt @100kHz
  115. ISR (TIMER1_COMPA_vect)
  116. {
  117. PORTC = 0xFF;
  118. pwm_pointer++;
  119. if (pwm_pointer<50)
  120. {
  121. PORTD = 0xFF;
  122. }
  123. else if (pwm_pointer<250)
  124. {
  125. PORTD = timetable[pwm_pointer - 50];
  126. }
  127. else
  128. {
  129. PORTD = 0x00;
  130. if (pwm_pointer>=2000)
  131. {
  132. pwm_pointer = 0;//20ms * 100/ms
  133. }
  134. }
  135. PORTC = 0x00;
  136. }
  137.  
  138. //spi.h
  139. /*
  140. * File: simple SPI routines for AVR
  141. * Author: Tuomas Nylund ([email protected])
  142. * Website: http://tuomasnylund.fi
  143. *
  144. * This program is free software: you can redistribute it and/or modify
  145. * it under the terms of the GNU General Public License as published by
  146. * the Free Software Foundation, either version 3 of the License, or
  147. * (at your option) any later version.
  148. *
  149. * This program is distributed in the hope that it will be useful,
  150. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  151. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  152. * GNU General Public License for more details.
  153. *
  154. * You should have received a copy of the GNU General Public License
  155. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  156. */
  157.  
  158. #ifndef SPI_H_
  159. #define SPI_H_
  160.  
  161. #include <avr/io.h>
  162.  
  163. #define SPI_DDR DDRB
  164. #define SPI_MOSI_BIT PB2
  165. #define SPI_SCK_BIT PB1
  166. #define SPI_CS_BIT PB0
  167.  
  168. #define SPIMODE0 (0<<CPHA)
  169. #define SPIMODE1 (1<<CPHA)
  170. #define SPIMODE2 (2<<CPHA)
  171. #define SPIMODE3 (3<<CPHA)
  172.  
  173. #define LSB_FIRST (1<<DORD)
  174. #define MSB_FIRST (0<<DORD)
  175.  
  176. #define CLOCKDIV4 (0<<SPR0)
  177. #define CLOCKDIV16 (1<<SPR0)
  178. #define CLOCKDIV64 (2<<SPR0)
  179.  
  180. #define SPI_BUFFER_SIZE 18
  181.  
  182. void spi_init(void);
  183.  
  184. void spi_send_byte(uint8_t data);
  185.  
  186. uint8_t spi_read_byte(void);
  187.  
  188. volatile uint8_t buffer_finished;
  189. volatile uint8_t spi_buffer[SPI_BUFFER_SIZE];
  190.  
  191. #endif
  192.  
  193. //spi.c
  194. #include <avr/io.h>
  195. #include <avr/interrupt.h>
  196. #include <string.h>
  197.  
  198. #include "spi.h"
  199.  
  200. void spi_init(void){
  201. //Set MoSi as input, we will only receive
  202. SPI_DDR |= (1<<SPI_MOSI_BIT);
  203. //Enable SPI and SPI interrupts
  204. SPCR = (1<<SPE) | (1<<SPIE);
  205. }
  206.  
  207. void spi_send_byte(uint8_t data){
  208. SPDR = data;
  209. //Wait for stuff to be finished
  210. while(!(SPSR & (1<<SPIF)));
  211. }
  212.  
  213. uint8_t spi_read_byte(void){
  214. SPDR = 0x00;
  215. while(!(SPSR & (1<<SPIF)));
  216. return SPDR;
  217. }
  218.  
  219.  
  220. //Buffer to store SPI data in
  221. volatile uint8_t spi_buffer[SPI_BUFFER_SIZE];
  222. //Pointer to indicate progression in the buffer
  223. volatile uint8_t buffer_pointer = 0;
  224. //Boolean flag to indicate a message was fully received
  225. volatile uint8_t buffer_finished = 0;
  226.  
  227. //Receive SPI commands
  228. ISR(SPI_STC_vect)
  229. {
  230. //Read received byte
  231. uint8_t received = SPDR;
  232. SPDR = 0x00;
  233. if (received==0x00)
  234. {
  235. buffer_pointer = 0;
  236. }
  237. spi_buffer[buffer_pointer] = received;
  238. //Progress the pointer, and wrap if neccessary
  239. buffer_pointer++;
  240. if (buffer_pointer>=SPI_BUFFER_SIZE)
  241. {
  242. buffer_pointer = 0;
  243. buffer_finished = 1;
  244. }
  245. }
Advertisement
Add Comment
Please, Sign In to add comment