Browse Source

add divider for arbitrary HSPI clock frequencies

devsaurus 8 years ago
parent
commit
ac50f9c6a5
5 changed files with 23 additions and 13 deletions
  1. 12 6
      app/driver/spi.c
  2. 1 1
      app/include/driver/spi.h
  3. 7 3
      app/modules/spi.c
  4. 2 2
      app/platform/platform.c
  5. 1 1
      app/platform/platform.h

+ 12 - 6
app/driver/spi.c

@@ -64,7 +64,7 @@ void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit)
  * Description  : SPI master initial function for common byte units transmission
  * Parameters   : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
 *******************************************************************************/
-void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock)
+void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock_div)
 {
 	uint32 regvalue; 
 
@@ -109,12 +109,18 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databi
 	//clear Daul or Quad lines transmission mode
 	CLEAR_PERI_REG_MASK(SPI_CTRL(spi_no), SPI_QIO_MODE|SPI_DIO_MODE|SPI_DOUT_MODE|SPI_QOUT_MODE);
 
-	// SPI clock=CPU clock/8
+	// SPI clock = CPU clock / clock_div
+	// the divider needs to be a multiple of 2 to get a proper waveform shape
+	if ((clock_div & 0x01) != 0) {
+		// bump the divider to the nextN*2
+		clock_div += 0x02;
+	}
+	clock_div >>= 1;
 	WRITE_PERI_REG(SPI_CLOCK(spi_no), 
-					((1&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)|
-					((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
-					((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
-					((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
+					((clock_div&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)|
+					((1&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
+					((0&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
+					((1&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
 
 	//set 8bit output buffer length, the buffer is the low 8bit of register"SPI_FLASH_C0"
 	WRITE_PERI_REG(SPI_USER1(spi_no), 

+ 1 - 1
app/include/driver/spi.h

@@ -18,7 +18,7 @@ void spi_lcd_mode_init(uint8 spi_no);
 void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit);
 
 //spi master init funtion
-void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock);
+void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock_div);
 //use spi send 8bit data
 void spi_mast_byte_write(uint8 spi_no,uint8 *data);
 

+ 7 - 3
app/modules/spi.c

@@ -7,7 +7,7 @@
 #include "auxmods.h"
 #include "lrotable.h"
 
-// Lua: = spi.setup( id, mode, cpol, cpha, databits, clock )
+// Lua: = spi.setup( id, mode, cpol, cpha, databits, clock_div )
 static int spi_setup( lua_State *L )
 {
   unsigned id = luaL_checkinteger( L, 1 );
@@ -15,7 +15,7 @@ static int spi_setup( lua_State *L )
   unsigned cpol = luaL_checkinteger( L, 3 );
   unsigned cpha = luaL_checkinteger( L, 4 );
   unsigned databits = luaL_checkinteger( L, 5 );
-  uint32_t clock = luaL_checkinteger( L, 6 );
+  uint32_t clock_div = luaL_checkinteger( L, 6 );
 
   MOD_CHECK_ID( spi, id );
 
@@ -35,7 +35,11 @@ static int spi_setup( lua_State *L )
     return luaL_error( L, "wrong arg type" );
   }
 
-  u32 res = platform_spi_setup(id, mode, cpol, cpha, databits, clock);
+  if (clock_div < 4) {
+    return luaL_error( L, "invalid clock divider" );
+  }
+
+  u32 res = platform_spi_setup(id, mode, cpol, cpha, databits, clock_div);
   lua_pushinteger( L, res );
   return 1;
 }

+ 2 - 2
app/platform/platform.c

@@ -445,9 +445,9 @@ int platform_i2c_recv_byte( unsigned id, int ack ){
 
 // *****************************************************************************
 // SPI platform interface
-uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock)
+uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock_div)
 {
-  spi_master_init(id, cpol, cpha, databits, clock);
+  spi_master_init(id, cpol, cpha, databits, clock_div);
   return 1;
 }
 

+ 1 - 1
app/platform/platform.h

@@ -100,7 +100,7 @@ typedef uint32_t spi_data_type;
 
 // The platform SPI functions
 int platform_spi_exists( unsigned id );
-uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock);
+uint32_t platform_spi_setup( unsigned id, int mode, unsigned cpol, unsigned cpha, unsigned databits, uint32_t clock_div);
 spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data );
 void platform_spi_select( unsigned id, int is_select );