Hello to all,
I made a project with ATSAML21E18B connected to a shift register, using only SCLK and MOSI pins. I want to use the DMAC to send datas.
I connected the SPI pins to a signal analyzer and I program/debugg it with the Segger J-Link.
I noticed a strange behavior that I can't solve: using Atmel Studio the firmware works, but if I use Keil ARM 5.29 the DMA doesn't work.
Everything is compiled and started, it seems to set up all hardware devices correctly, but when my code calls the "spi_m_dma_transfer(...)" function (line 65) with Keil nothing flows out from SPI pins.
spi_m_dma_transfer (...) source code is in \hal\src\hal_spi_m_dma.c and it calls _spi_m_dma_transfer (...) in \hpl\sercom\hpl_sercom.c
with the debugger I can see that the function returns ERR_NONE, but nothing flows out the SPI PINs, connected to the logic analyzer.
I'm trying to understand how the same code could work differently using two IDEs.
I thought it depended on the compiler so I did a further test: used Keil with the GCC.
after a week of sleepless nights I can say that:
Atmel Studio + GCC: works
Keil + ARMCC 5.06: does not work
Keil + GCC: it does not work
I don't know what test it can still do. I am attaching the main.c file and the three different projects. I hope some of you can help me!
#include <atmel_start.h>
#define DELAY_SHORT 50
#define SPI_LED_HARDWARE SERCOM0 // value UART hardware peripheral
static uint8_t tx_stream[10] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81};
struct spi_m_dma_descriptor SPI_LED;
/* simple delay made by while loop */
static void delay_short( void ) {
volatile uint32_t t = 0;
while( t < DELAY_SHORT ) { t++; }
return;
}
/* Transfer completed callback */
static void vUtil_DMA_transfer_SPI_LED( struct _dma_resource *resource ) {
while( hri_sercomspi_get_INTFLAG_TXC_bit( SPI_LED_HARDWARE ) == 0 ); // wait for the last bit is sent
gpio_set_pin_level( STAT_LED, true ); // turn ON the status LED
delay_short(); // wait
gpio_set_pin_level( STAT_LED, false ); // turn OFF the status LED
delay_short(); // wait
}
int main( void ) {
init_mcu(); // system_init
// SPI_LED_CLOCK_init
hri_gclk_write_PCHCTRL_reg( GCLK, SERCOM0_GCLK_ID_CORE, CONF_GCLK_SERCOM0_CORE_SRC | ( 1 << GCLK_PCHCTRL_CHEN_Pos ) );
hri_gclk_write_PCHCTRL_reg( GCLK, SERCOM0_GCLK_ID_SLOW, CONF_GCLK_SERCOM0_SLOW_SRC | ( 1 << GCLK_PCHCTRL_CHEN_Pos ) );
hri_mclk_set_APBCMASK_SERCOM0_bit( MCLK );
// SPI_LED_init
spi_m_dma_init( &SPI_LED, SERCOM0 ); // init the DMA using HAL function
// SPI_LED_PORT_init
gpio_set_pin_direction( LED_MISO, GPIO_DIRECTION_IN );
gpio_set_pin_pull_mode( LED_MISO, GPIO_PULL_OFF );
gpio_set_pin_function( LED_MISO, PINMUX_PA04D_SERCOM0_PAD0 );
gpio_set_pin_level( LED_SCLK, false );
gpio_set_pin_direction( LED_SCLK, GPIO_DIRECTION_OUT );
gpio_set_pin_function( LED_SCLK, PINMUX_PA05D_SERCOM0_PAD1 );
gpio_set_pin_level( LED_MOSI, false );
gpio_set_pin_direction( LED_MOSI, GPIO_DIRECTION_OUT );
gpio_set_pin_function( LED_MOSI, PINMUX_PA07D_SERCOM0_PAD3 );
// status LED init
gpio_set_pin_function( STAT_LED, GPIO_PIN_FUNCTION_OFF ); // no special function on PIN
gpio_set_pin_direction( STAT_LED, GPIO_DIRECTION_OUT ); // PIN setted as OUT
gpio_set_pin_level( STAT_LED, false ); // turn OFF the status LED
//
spi_m_dma_register_callback( &SPI_LED, SPI_M_DMA_CB_TX_DONE, vUtil_DMA_transfer_SPI_LED ); // set the callback function for DMA operations
spi_m_dma_enable( &SPI_LED ); // enable the DMA
while( 1 ) {
tx_stream[0] = 0x00;
tx_stream[1] = 0x01;
tx_stream[2] = 0x04;
tx_stream[3] = 0x01;
tx_stream[4] = 0x00;
tx_stream[5] = 0x01;
tx_stream[6] = 0x00;
tx_stream[7] = 0x01;
tx_stream[8] = 0x00;
tx_stream[9] = 0x01;
spi_m_dma_transfer( &SPI_LED, tx_stream, NULL, 10 ); // this function does not work well in KEIL
// I connected a logic analyzer on SPI pins, and I use J-Link debugger
// this is what i see:
// calls spi_m_dma_transfer (...) is in \hal\src\hal_spi_m_dma.c
// then calls _spi_m_dma_transfer (...) in \hpl\sercom\hpl_sercom.c
// returns ERR_NONE
// but nothing flow out the SPI PINs, connected to a logic analyzer
// also with keil the CPU never calls vUtil_DMA_transfer_SPI_LED
delay_short();
}
return 0;
}