void main (void) { char keypress; WDTCN = 0xde; // disable watchdog timer WDTCN = 0xad; SYSCLK_Init (); // initialize oscillator //PORT_Init (); // initialize crossbar and GPIO UART0_Init (); // initialize UART0 //OSCICN |= 0x03; // Set internal oscillator to highest setting // (16 MHz) XBR0 = 0x05; // Route SMBus to GPIO pins through crossbar XBR2 = 0x44; // Enable crossbar and weak pull-ups P1MDOUT = 0x03; SMB0CN = 0x44; // Enable SMBus with ACKs on acknowledge // cycle SMB0CR = -80; // SMBus clock rate = 100kHz. EIE1 |= 2; // SMBus interrupt enable EA = 1; // Global interrupt enable SM_BUSY = 0; // Free SMBus for first transfer. //SMBus_Init(); //Timer3_Init(); //Interrupts_Init(); //SI = 0; printf ("EE587 Experiment #3\n"); printf ("Initialization Complete...\n"); while (1) { printf("what would you like to do? (d,b,r,w):"); keypress = getchar(); printf("\n"); switch(keypress) { case 'd': dump_eeprom(); break; case 'b': block_fill(); break; case 'r': read_eeprom(); break; case 'w': write_eeprom(); break; case ' ':; default: printf("Invalid Command '%c'\n",keypress); break; } } // while(1) } // main
/** * * \brief Test search and double buffering (link) modes * * \note This function tests search and double buffering features of the EDMA * controller by configuring channel 2 searching data. In case of success, the * channel 0 is automatically (double buffering) enables (if it is * successfull) and copies a memory block. The copy is verified. * * \param test Current test case */ static void run_edma_search_dbuf_test(const struct test_case *test) { struct edma_channel_config ch0_config_params; struct edma_channel_config ch2_config_params; bool success; /* Fill source block with pattern data */ set_buffer(memory_block_src, 0x00); block_fill(memory_block_src, MEMORY_BLOCK_SIZE); /* Null out the destination block */ set_buffer(memory_block_dest, 0x00); /* Null out the config params */ memset(&ch0_config_params, 0, sizeof(ch0_config_params)); memset(&ch2_config_params, 0, sizeof(ch2_config_params)); /* Enable EDMA module, Channels 0 and 2 in standard configuration */ edma_enable(EDMA_CHMODE_STD02_gc); /* Enable double buffering mode on channel 0 and 1 */ edma_set_double_buffer_mode(EDMA_DBUFMODE_BUF0123_gc); /* Set channel 2 to search data (last byte of memory_block_src[]) */ edma_channel_set_src_reload_mode(&ch2_config_params, EDMA_CH_RELOAD_NONE_gc); edma_channel_set_src_dir_mode(&ch2_config_params, EDMA_CH_DIR_INC_gc); edma_channel_set_dest_reload_mode(&ch2_config_params, EDMA_CH_RELOAD_NONE_gc); edma_channel_set_search_mode(&ch2_config_params, EDMA_CH_DESTDIR_MP1_gc); edma_channel_set_burst_length(&ch2_config_params, EDMA_CH_BURSTLEN_1BYTE_gc); edma_channel_set_trigger_source(&ch2_config_params, EDMA_CH_TRIGSRC_OFF_gc); edma_channel_set_transfer_count16(&ch2_config_params, MEMORY_BLOCK_SIZE); edma_channel_set_source_address(&ch2_config_params, (uint16_t)(uintptr_t)memory_block_src); edma_channel_set_search_data(&ch2_config_params, memory_block_src[MEMORY_BLOCK_SIZE - 1], 0xFF); /* Write config channel 2 */ edma_channel_write_config(EDMA_CH_2, &ch2_config_params); /* * Set channel 0 to copy from memory_block_src[] to memory_block_dest[] * once a match will occur on channel 2. There will be no transfer if no * match occurs. */ edma_channel_set_repeat(&ch0_config_params); edma_channel_set_burst_length(&ch0_config_params, EDMA_CH_BURSTLEN_2BYTE_gc); edma_channel_set_src_reload_mode(&ch0_config_params, EDMA_CH_RELOAD_TRANSACTION_gc); edma_channel_set_dest_reload_mode(&ch0_config_params, EDMA_CH_RELOAD_TRANSACTION_gc); edma_channel_set_src_dir_mode(&ch0_config_params, EDMA_CH_DIR_INC_gc); edma_channel_set_dest_dir_mode(&ch0_config_params, EDMA_CH_DESTDIR_INC_gc); edma_channel_set_trigger_source(&ch0_config_params, EDMA_CH_TRIGSRC_OFF_gc); edma_channel_set_transfer_count16(&ch0_config_params, MEMORY_BLOCK_SIZE); edma_channel_set_source_address(&ch0_config_params, (uint16_t)(uintptr_t)memory_block_src); edma_channel_set_destination_address(&ch0_config_params, (uint16_t)(uintptr_t)memory_block_dest); /* Write config channel 0 */ edma_channel_write_config(EDMA_CH_0, &ch0_config_params); /* Enable only channel 2 */ edma_channel_enable(EDMA_CH_2); /* Transfer block and wait for it to finish */ edma_channel_trigger_block_transfer(EDMA_CH_2); edma_channel_trigger_block_transfer(EDMA_CH_0); /* Wait for search completion */ while (edma_get_channel_status(EDMA_CH_2) != EDMA_CH_TRANSFER_COMPLETED) { /* Intentionally left empty */ } /* Wait for transfer completion */ while (edma_get_channel_status(EDMA_CH_0) != EDMA_CH_TRANSFER_COMPLETED) { /* Intentionally left empty */ } /* Disable EDMA */ edma_disable(); /* Verify that the search result is as expected */ success = block_compare( edma_channel_get_search_pointer(EDMA_CH_2), &memory_block_src[MEMORY_BLOCK_SIZE - 1], 1); test_assert_true(test, success, "SEARCH mode did not function properly"); /* Verify that the transfer result is as expected */ success = block_compare(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); test_assert_true(test, success, "DOUBLE BUFFER mode did not function properly"); }
/** * * \brief Test double buffering mode * * \note This function tests the double buffering feature of the DMA * controller by configuring channel 0 and 1 to do the same copy, * and verify that the channels enable each other according to * the double buffering process. * * \param test Current test case */ static void run_dma_double_buffering_test(const struct test_case *test) { struct dma_channel_config config_params; bool success = true; /* Assume everything goes well */ /* Fill source block with pattern data */ set_buffer(memory_block_src, 0x00); block_fill(memory_block_src, MEMORY_BLOCK_SIZE); /* Null out the destination block */ set_buffer(memory_block_dest, 0x00); /* Null out the config params */ memset(&config_params, 0, sizeof(config_params)); /* Enable DMA */ dma_enable(); /* Enable double buffering mode on channel 0 and 1 */ dma_set_double_buffer_mode(DMA_DBUFMODE_CH01_gc); /* Set channel 1 to copy from memory_block_src to memory_block_dest */ dma_channel_set_src_reload_mode(&config_params, DMA_CH_SRCRELOAD_NONE_gc); dma_channel_set_src_dir_mode(&config_params, DMA_CH_SRCDIR_INC_gc); dma_channel_set_dest_reload_mode(&config_params, DMA_CH_DESTRELOAD_NONE_gc); dma_channel_set_dest_dir_mode(&config_params, DMA_CH_DESTDIR_INC_gc); dma_channel_set_burst_length(&config_params, DMA_CH_BURSTLEN_1BYTE_gc); dma_channel_set_transfer_count(&config_params, MEMORY_BLOCK_SIZE); dma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t)memory_block_src); dma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t)memory_block_dest); dma_channel_set_repeats(&config_params, DOUBLE_BUFFER_REPEATS); /* Write config and enable */ dma_channel_write_config(DMA_CHANNEL_0, &config_params); dma_channel_write_config(DMA_CHANNEL_1, &config_params); /* Enable only channel 0 */ dma_channel_enable(DMA_CHANNEL_0); /* Transfer block and wait for it to finish */ dma_channel_trigger_block_transfer(DMA_CHANNEL_0); while (dma_get_channel_status(DMA_CHANNEL_0) != DMA_CH_TRANSFER_COMPLETED) { /* Intentionally left empty */ } /* * If double buffering is working, channel 1 * will be enabled now by the controller */ if (!(dma_channel_is_enabled(DMA_CHANNEL_1))) { success = false; } /* * Disable channel 0, transfer channel 1, * and verify that channel 0 is enabled again by the controller */ dma_channel_disable(DMA_CHANNEL_0); /* Transfer block and wait for it to finish */ dma_channel_trigger_block_transfer(DMA_CHANNEL_1); while (dma_get_channel_status(DMA_CHANNEL_1) != DMA_CH_TRANSFER_COMPLETED) { /* Intentionally left empty */ } /* Verify that channel 0 is enabled again */ if (!(dma_channel_is_enabled(DMA_CHANNEL_0))) { success = false; } test_assert_true(test, success, "Double buffering mode did not function properly"); }
/** * \brief Test the different burst lengths by copying on all channels * * \note This test copies a memory block using different burst lengths, * and verifies that they have been copied correctly, thereby testing both * burst lengths and memory transfer. * * \param test Current test */ static void run_edma_memory_copy_burst_length_test(const struct test_case *test) { struct edma_channel_config config_params; edma_channel_num_t channel_index; bool success = true; /* Assume everything goes well */ /* Fill the source block with our known pattern */ set_buffer(memory_block_src, 0x00); block_fill(memory_block_src, MEMORY_BLOCK_SIZE); /* Null out the config params */ memset(&config_params, 0, sizeof(config_params)); /* Enable EDMA, channels 0 and 2 in standard conf. */ edma_enable(EDMA_CHMODE_STD02_gc); /* * - No reload on source and destination * - Increment source and destination */ edma_channel_set_src_reload_mode(&config_params, EDMA_CH_RELOAD_NONE_gc); edma_channel_set_src_dir_mode(&config_params, EDMA_CH_DIR_INC_gc); edma_channel_set_dest_reload_mode(&config_params, EDMA_CH_RELOAD_NONE_gc); edma_channel_set_dest_dir_mode(&config_params, EDMA_CH_DESTDIR_INC_gc); edma_channel_set_transfer_count16(&config_params, MEMORY_BLOCK_SIZE); edma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t)memory_block_src); edma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t)memory_block_dest); /* Test burst lengths on all standard channels */ for (channel_index = EDMA_CH_0; channel_index < EDMA_NUMBER_OF_STANDARD_CHANNELS; channel_index += 2) { edma_channel_set_burst_length(&config_params, EDMA_CH_BURSTLEN_1BYTE_gc); edma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ edma_channel_enable(channel_index); ut_edma_transfer_block(channel_index); edma_channel_disable(channel_index); /* Check that source and destination are equal */ success = block_compare(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); if (!success) { break; } /* Reset channel and write 2 byte burst length */ edma_channel_reset(channel_index); edma_channel_set_burst_length(&config_params, EDMA_CH_BURSTLEN_2BYTE_gc); edma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ edma_channel_enable(channel_index); ut_edma_transfer_block(channel_index); edma_channel_disable(channel_index); /* Check that source and destination are equal */ success = block_compare(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); /* test_assert_true(test, false, "Test-1 "); */ if (!success) { break; } } /* Disable EDMA */ edma_disable(); test_assert_true(test, success, "EDMA burst mode memory copy tests failed on StdCH_%d", channel_index); }
/** * \brief Test different directions on all channels * * \note This test copies the source memory block into the destination block * in different ways. * * \param test Current test */ static void run_dma_direction_test(const struct test_case *test) { struct dma_channel_config config_params; uint8_t channel_index; bool success = true; /* Assume everything goes well */ /* Fill the source block with our known pattern */ set_buffer(memory_block_src, 0x00); block_fill(memory_block_src, MEMORY_BLOCK_SIZE); /* Null out the config params */ memset(&config_params, 0, sizeof(config_params)); /* Enable DMA */ dma_enable(); /* No reload on source and destination */ dma_channel_set_src_reload_mode(&config_params, DMA_CH_SRCRELOAD_NONE_gc); dma_channel_set_dest_reload_mode(&config_params, DMA_CH_DESTRELOAD_NONE_gc); dma_channel_set_transfer_count(&config_params, MEMORY_BLOCK_SIZE); dma_channel_set_burst_length(&config_params, DMA_CH_BURSTLEN_1BYTE_gc); /* Test a memory transfer on all channels */ for (channel_index = 0; channel_index < DMA_NUMBER_OF_CHANNELS; channel_index++) { /* Reset channel and write the configuration */ dma_channel_reset(channel_index); /* Increment source, increment destination */ dma_channel_set_src_dir_mode(&config_params, DMA_CH_SRCDIR_INC_gc); dma_channel_set_dest_dir_mode(&config_params, DMA_CH_DESTDIR_INC_gc); /* Data starts from the first byte */ dma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t)memory_block_src); dma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t)memory_block_dest); /* Write the config */ dma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ dma_channel_enable(channel_index); dma_transfer_block(channel_index); dma_channel_disable(channel_index); /* Check that source and destination are equal */ success = block_compare(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); if (!success) { break; } /* Reset channel and write the configuration */ dma_channel_reset(channel_index); /* Decrement source, increment destination */ dma_channel_set_src_dir_mode(&config_params, DMA_CH_SRCDIR_DEC_gc); dma_channel_set_dest_dir_mode(&config_params, DMA_CH_DESTDIR_INC_gc); /* Data starts from the first byte */ dma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t) (memory_block_src + MEMORY_BLOCK_SIZE - 1)); dma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t)memory_block_dest); /* Write the config */ dma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ dma_channel_enable(channel_index); dma_transfer_block(channel_index); dma_channel_disable(channel_index); /* Check that destination is the reverse of source */ success = block_compare_reverse(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); if (!success) { break; } /* Reset channel and write the configuration */ dma_channel_reset(channel_index); /* Decrement source, increment destination */ dma_channel_set_src_dir_mode(&config_params, DMA_CH_SRCDIR_INC_gc); dma_channel_set_dest_dir_mode(&config_params, DMA_CH_DESTDIR_DEC_gc); /* Data starts from the first byte */ dma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t)memory_block_src); dma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t) (memory_block_dest + MEMORY_BLOCK_SIZE - 1)); /* Write the config */ dma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ dma_channel_enable(channel_index); dma_transfer_block(channel_index); dma_channel_disable(channel_index); /* Check that destination is the reverse of source */ success = block_compare_reverse(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); if (!success) { break; } /* Reset channel and write the configuration */ dma_channel_reset(channel_index); /* Decrement source, Decrement destination */ dma_channel_set_src_dir_mode(&config_params, DMA_CH_SRCDIR_DEC_gc); dma_channel_set_dest_dir_mode(&config_params, DMA_CH_DESTDIR_DEC_gc); /* Data starts from the first byte */ dma_channel_set_source_address(&config_params, (uint16_t)(uintptr_t) (memory_block_src + MEMORY_BLOCK_SIZE - 1)); dma_channel_set_destination_address(&config_params, (uint16_t)(uintptr_t) (memory_block_dest + MEMORY_BLOCK_SIZE - 1)); /* Write the config */ dma_channel_write_config(channel_index, &config_params); /* Clear destination */ set_buffer(memory_block_dest, 0x00); /* Enable channel, transfer, and disable it */ dma_channel_enable(channel_index); dma_transfer_block(channel_index); dma_channel_disable(channel_index); /* Check that source and destination are equal */ success = block_compare(memory_block_src, memory_block_dest, MEMORY_BLOCK_SIZE); if (!success) { break; } } /* Disable DMA */ dma_disable(); test_assert_true(test, success, "DMA direction copy test failed on channel %d", channel_index); }