vserprog.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #include <stdbool.h>
  2. #include <libopencm3/stm32/rcc.h>
  3. #include <libopencm3/stm32/gpio.h>
  4. #include <libopencm3/cm3/nvic.h>
  5. #include <libopencm3/usb/usbd.h>
  6. #ifdef STM32F0
  7. #include <libopencm3/stm32/crs.h>
  8. #include <libopencm3/stm32/syscfg.h>
  9. #endif /* STM32F0 */
  10. #include "serprog.h"
  11. #define BUS_SPI (1 << 3)
  12. #include "board.h"
  13. #include "usbcdc.h"
  14. #include "spi.h"
  15. #define S_IFACE_VERSION 0x01 /* Currently version 1 */
  16. #define S_PGM_NAME "stm32-vserprog" /* The program's name, must < 16 bytes */
  17. #define S_SUPPORTED_BUS BUS_SPI
  18. #define S_CMD_MAP ( \
  19. (1 << S_CMD_NOP) | \
  20. (1 << S_CMD_Q_IFACE) | \
  21. (1 << S_CMD_Q_CMDMAP) | \
  22. (1 << S_CMD_Q_PGMNAME) | \
  23. (1 << S_CMD_Q_SERBUF) | \
  24. (1 << S_CMD_Q_BUSTYPE) | \
  25. (1 << S_CMD_SYNCNOP) | \
  26. (1 << S_CMD_O_SPIOP) | \
  27. (1 << S_CMD_S_BUSTYPE) | \
  28. (1 << S_CMD_S_SPI_FREQ)| \
  29. (1 << S_CMD_S_PIN_STATE) \
  30. )
  31. #ifdef STM32F0
  32. #define LED_ENABLE() { \
  33. gpio_mode_setup(BOARD_PORT_LED, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BOARD_PIN_LED); \
  34. gpio_set_output_options(BOARD_PORT_LED, GPIO_OTYPE_PP, GPIO_OSPEED_LOW, BOARD_PIN_LED); \
  35. }
  36. #define LED_DISABLE() gpio_mode_setup(BOARD_PORT_LED, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BOARD_PIN_LED);
  37. #else
  38. #define LED_ENABLE() gpio_set_mode(BOARD_PORT_LED, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, BOARD_PIN_LED)
  39. #define LED_DISABLE() gpio_set_mode(BOARD_PORT_LED, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, BOARD_PIN_LED)
  40. #endif /* STM32F0 */
  41. #if BOARD_LED_HIGH_IS_BUSY
  42. #define LED_BUSY() gpio_set(BOARD_PORT_LED, BOARD_PIN_LED)
  43. #define LED_IDLE() gpio_clear(BOARD_PORT_LED, BOARD_PIN_LED)
  44. #else
  45. #define LED_BUSY() gpio_clear(BOARD_PORT_LED, BOARD_PIN_LED)
  46. #define LED_IDLE() gpio_set(BOARD_PORT_LED, BOARD_PIN_LED)
  47. #endif /* BOARD_LED_HIGH_IS_BUSY */
  48. void handle_command(unsigned char command) {
  49. static uint8_t i; /* Loop */
  50. static uint8_t l; /* Length */
  51. static uint32_t slen; /* SPIOP write length */
  52. static uint32_t rlen; /* SPIOP read length */
  53. static uint32_t freq_req; /* Requested SPI clock */
  54. LED_BUSY();
  55. switch(command) {
  56. case S_CMD_NOP: {
  57. usbcdc_putc(S_ACK);
  58. break;
  59. }
  60. case S_CMD_Q_IFACE: {
  61. // TODO: use usbcdc_write for better efficiency
  62. usbcdc_putc(S_ACK);
  63. /* little endian multibyte value to complete to 16bit */
  64. usbcdc_putc(S_IFACE_VERSION);
  65. usbcdc_putc(0);
  66. break;
  67. }
  68. case S_CMD_Q_CMDMAP: {
  69. // TODO: use usbcdc_write for better efficiency
  70. usbcdc_putc(S_ACK);
  71. /* little endian */
  72. usbcdc_putu32(S_CMD_MAP);
  73. for(i = 0; i < 32 - sizeof(uint32_t); i++) {
  74. usbcdc_putc(0);
  75. }
  76. break;
  77. }
  78. case S_CMD_Q_PGMNAME: {
  79. // TODO: use usbcdc_write for better efficiency
  80. usbcdc_putc(S_ACK);
  81. l = 0;
  82. while(S_PGM_NAME[l]) {
  83. usbcdc_putc(S_PGM_NAME[l]);
  84. l ++;
  85. }
  86. for(i = l; i < 16; i++) {
  87. usbcdc_putc(0);
  88. }
  89. break;
  90. }
  91. case S_CMD_Q_SERBUF: {
  92. // TODO: use usbcdc_write for better efficiency
  93. usbcdc_putc(S_ACK);
  94. /* Pretend to be 64K (0xffff) */
  95. usbcdc_putc(0xff);
  96. usbcdc_putc(0xff);
  97. break;
  98. }
  99. case S_CMD_Q_BUSTYPE: {
  100. // TODO: use usbcdc_write for better efficiency
  101. // TODO: LPC / FWH IO support via PP-Mode
  102. usbcdc_putc(S_ACK);
  103. usbcdc_putc(S_SUPPORTED_BUS);
  104. break;
  105. }
  106. case S_CMD_Q_CHIPSIZE: {
  107. break;
  108. }
  109. case S_CMD_Q_OPBUF: {
  110. // TODO: opbuf function 0
  111. break;
  112. }
  113. case S_CMD_Q_WRNMAXLEN: {
  114. break;
  115. }
  116. case S_CMD_R_BYTE: {
  117. break;
  118. }
  119. case S_CMD_R_NBYTES: {
  120. break;
  121. }
  122. case S_CMD_O_INIT: {
  123. break;
  124. }
  125. case S_CMD_O_WRITEB: {
  126. // TODO: opbuf function 1
  127. break;
  128. }
  129. case S_CMD_O_WRITEN: {
  130. // TODO: opbuf function 2
  131. break;
  132. }
  133. case S_CMD_O_DELAY: {
  134. // TODO: opbuf function 3
  135. break;
  136. }
  137. case S_CMD_O_EXEC: {
  138. // TODO: opbuf function 4
  139. break;
  140. }
  141. case S_CMD_SYNCNOP: {
  142. // TODO: use usbcdc_write for better efficiency
  143. usbcdc_putc(S_NAK);
  144. usbcdc_putc(S_ACK);
  145. break;
  146. }
  147. case S_CMD_Q_RDNMAXLEN: {
  148. // TODO
  149. break;
  150. }
  151. case S_CMD_S_BUSTYPE: {
  152. /* We do not have multiplexed bus interfaces,
  153. * so simply ack on supported types, no setup needed. */
  154. if((usbcdc_getc() | S_SUPPORTED_BUS) == S_SUPPORTED_BUS) {
  155. usbcdc_putc(S_ACK);
  156. } else {
  157. usbcdc_putc(S_NAK);
  158. }
  159. break;
  160. }
  161. case S_CMD_O_SPIOP: {
  162. slen = usbcdc_getu24();
  163. rlen = usbcdc_getu24();
  164. SPI_SELECT();
  165. /* TODO: handle errors with S_NAK */
  166. if(slen) {
  167. spi_bulk_write(slen);
  168. }
  169. usbcdc_putc(S_ACK); // TODO: S_ACK early for better performance (so while DMA is working, programmer can receive next command)?
  170. if(rlen) {
  171. spi_bulk_read(rlen); // TODO: buffer?
  172. }
  173. SPI_UNSELECT();
  174. break;
  175. }
  176. case S_CMD_S_SPI_FREQ: {
  177. freq_req = usbcdc_getu32();
  178. if(freq_req == 0) {
  179. usbcdc_putc(S_NAK);
  180. } else {
  181. usbcdc_putc(S_ACK);
  182. usbcdc_putu32(spi_setup(freq_req));
  183. }
  184. break;
  185. }
  186. case S_CMD_S_PIN_STATE: {
  187. if( usbcdc_getc() )
  188. spi_enable_pins();
  189. else
  190. spi_disable_pins();
  191. usbcdc_putc(S_ACK);
  192. break;
  193. }
  194. default: {
  195. break; // TODO: notify protocol failure malformed command
  196. }
  197. }
  198. LED_IDLE();
  199. }
  200. #ifdef GD32F103
  201. #define RCC_GCFGR_ADCPS_DIV12 ((uint32_t)0x10004000)
  202. #define RCC_GCFGR_ADCPS_DIV16 ((uint32_t)0x1000C000)
  203. #define RCC_GCFGR_USBPS_Div2_5 ((uint32_t)0x00800000)
  204. #define RCC_GCFGR_USBPS_Div2 ((uint32_t)0x00C00000)
  205. static void rcc_clock_setup_in_hse_12mhz_out_96mhz(void) {
  206. /* Enable internal high-speed oscillator. */
  207. rcc_osc_on(RCC_HSI);
  208. rcc_wait_for_osc_ready(RCC_HSI);
  209. /* Select HSI as SYSCLK source. */
  210. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
  211. /* Enable external high-speed oscillator 12MHz. */
  212. rcc_osc_on(RCC_HSE);
  213. rcc_wait_for_osc_ready(RCC_HSE);
  214. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
  215. /*
  216. * Set prescalers for AHB, ADC, ABP1, ABP2.
  217. * Do this before touching the PLL
  218. */
  219. rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 96MHz Max. 108MHz */
  220. rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8); /* Set. 12MHz Max. 14MHz */
  221. rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 48MHz Max. 54MHz */
  222. rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 96MHz Max. 108MHz */
  223. RCC_CFGR |= RCC_GCFGR_USBPS_Div2; /* USB Set. 48MHz Max. 48MHz */
  224. /* GD32 has 0-wait-state flash, do not touch anything! */
  225. /*
  226. * Set the PLL multiplication factor to 8.
  227. * 12MHz (external) * 8 (multiplier) = 96MHz
  228. */
  229. rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL8);
  230. /* Select HSE as PLL source. */
  231. rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
  232. /*
  233. * External frequency undivided before entering PLL
  234. * (only valid/needed for HSE).
  235. */
  236. rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
  237. /* Enable PLL oscillator and wait for it to stabilize. */
  238. rcc_osc_on(RCC_PLL);
  239. rcc_wait_for_osc_ready(RCC_PLL);
  240. /* Select PLL as SYSCLK source. */
  241. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
  242. /* Set the peripheral clock frequencies used */
  243. rcc_ahb_frequency = 96000000;
  244. rcc_apb1_frequency = 48000000;
  245. rcc_apb2_frequency = 96000000;
  246. }
  247. static void rcc_clock_setup_in_hse_12mhz_out_120mhz(void) {
  248. /* Enable internal high-speed oscillator. */
  249. rcc_osc_on(RCC_HSI);
  250. rcc_wait_for_osc_ready(RCC_HSI);
  251. /* Select HSI as SYSCLK source. */
  252. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
  253. /* Enable external high-speed oscillator 12MHz. */
  254. rcc_osc_on(RCC_HSE);
  255. rcc_wait_for_osc_ready(RCC_HSE);
  256. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
  257. /*
  258. * Set prescalers for AHB, ADC, ABP1, ABP2.
  259. * Do this before touching the PLL
  260. */
  261. rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /* Set. 120MHz Max. 108MHz */
  262. RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_ADCPRE) | RCC_GCFGR_ADCPS_DIV12; /* ADC Set. 10MHz Max. 14MHz */
  263. rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /* Set. 60MHz Max. 54MHz */
  264. rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /* Set. 120MHz Max. 108MHz */
  265. RCC_CFGR |= RCC_GCFGR_USBPS_Div2_5; /* USB Set. 48MHz Max. 48MHz */
  266. /* GD32 has 0-wait-state flash, do not touch anything! */
  267. /*
  268. * Set the PLL multiplication factor to 10.
  269. * 12MHz (external) * 10 (multiplier) = 120MHz
  270. */
  271. rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL10);
  272. /* Select HSE as PLL source. */
  273. rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
  274. /*
  275. * External frequency undivided before entering PLL
  276. * (only valid/needed for HSE).
  277. */
  278. rcc_set_pllxtpre(RCC_CFGR_PLLXTPRE_HSE_CLK);
  279. /* Enable PLL oscillator and wait for it to stabilize. */
  280. rcc_osc_on(RCC_PLL);
  281. rcc_wait_for_osc_ready(RCC_PLL);
  282. /* Select PLL as SYSCLK source. */
  283. rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
  284. /* Set the peripheral clock frequencies used */
  285. rcc_ahb_frequency = 120000000;
  286. rcc_apb1_frequency = 60000000;
  287. rcc_apb2_frequency = 120000000;
  288. }
  289. #endif /* GD32F103 */
  290. int main(void) {
  291. uint32_t i;
  292. rcc_periph_clock_enable(BOARD_RCC_LED);
  293. LED_ENABLE();
  294. LED_BUSY();
  295. /* Setup clock accordingly */
  296. #ifdef GD32F103
  297. rcc_clock_setup_in_hse_12mhz_out_120mhz();
  298. #else
  299. #ifdef STM32F0
  300. rcc_clock_setup_in_hsi48_out_48mhz();
  301. rcc_periph_clock_enable(RCC_SYSCFG_COMP);
  302. SYSCFG_CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
  303. rcc_periph_clock_enable(RCC_CRS);
  304. crs_autotrim_usb_enable();
  305. rcc_set_usbclk_source(RCC_HSI48);
  306. #else
  307. rcc_clock_setup_in_hse_8mhz_out_72mhz();
  308. #endif /* STM32F0 */
  309. #endif /* GD32F103 */
  310. rcc_periph_clock_enable(RCC_GPIOA); /* For USB */
  311. /* STM32F0x2 has internal pullup and does not need AFIO */
  312. #ifndef STM32F0
  313. rcc_periph_clock_enable(BOARD_RCC_USB_PULLUP);
  314. rcc_periph_clock_enable(RCC_AFIO); /* For SPI */
  315. #endif /* STM32F0 */
  316. #if BOARD_USE_DEBUG_PINS_AS_GPIO
  317. gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, AFIO_MAPR_TIM2_REMAP_FULL_REMAP);
  318. #endif
  319. /* Setup GPIO to pull up the D+ high. (STM32F0x2 has internal pullup.) */
  320. #ifndef STM32F0
  321. gpio_set_mode(BOARD_PORT_USB_PULLUP, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, BOARD_PIN_USB_PULLUP);
  322. #if BOARD_USB_HIGH_IS_PULLUP
  323. gpio_set(BOARD_PORT_USB_PULLUP, BOARD_PIN_USB_PULLUP);
  324. #else
  325. gpio_clear(BOARD_PORT_USB_PULLUP, BOARD_PIN_USB_PULLUP);
  326. #endif /* BOARD_USB_HIGH_IS_PULLUP */
  327. #endif /* STM32F0 */
  328. usbcdc_init();
  329. #ifdef HAS_BOARD_INIT
  330. board_init();
  331. #endif
  332. spi_setup(SPI_DEFAULT_CLOCK);
  333. /* The loop. */
  334. while (true) {
  335. /* Wait and blink if USB is not ready. */
  336. LED_IDLE();
  337. while (!usb_ready) {
  338. LED_DISABLE();
  339. for (i = 0; i < rcc_ahb_frequency / 150; i ++) {
  340. asm("nop");
  341. }
  342. LED_ENABLE();
  343. for (i = 0; i < rcc_ahb_frequency / 150; i ++) {
  344. asm("nop");
  345. }
  346. }
  347. /* Actual thing */
  348. /* TODO: we are blocked here, hence no knowledge about USB bet reset. */
  349. handle_command(usbcdc_getc());
  350. }
  351. return 0;
  352. }
  353. /* Interrupts (currently none here) */
  354. static void signal_fault(void) {
  355. uint32_t i;
  356. while (true) {
  357. LED_ENABLE();
  358. LED_BUSY();
  359. for (i = 0; i < 5000000; i ++) {
  360. asm("nop");
  361. }
  362. LED_DISABLE();
  363. for (i = 0; i < 5000000; i ++) {
  364. asm("nop");
  365. }
  366. }
  367. }
  368. void nmi_handler(void)
  369. __attribute__ ((alias ("signal_fault")));
  370. void hard_fault_handler(void)
  371. __attribute__ ((alias ("signal_fault")));